Skip to content

Commit fa98b0c

Browse files
committed
add more tests
1 parent de4689c commit fa98b0c

2 files changed

Lines changed: 126 additions & 200 deletions

File tree

packages/ra-data-local-forage/src/index.spec.ts

Lines changed: 63 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ jest.mock('localforage', () => ({
1313
}));
1414

1515
describe('ra-data-local-forage', () => {
16-
const posts = [
17-
{ id: 1, title: 'Hello world' },
18-
{ id: 2, title: 'Second post' },
19-
];
20-
2116
beforeEach(() => {
2217
jest.resetAllMocks();
2318
(localforage.keys as jest.Mock).mockResolvedValue([]);
@@ -39,83 +34,67 @@ describe('ra-data-local-forage', () => {
3934
);
4035
});
4136

42-
it('rejects unsafe resource keys', async () => {
43-
const dataProvider = localForageDataProvider();
44-
45-
await expect(
46-
dataProvider.update('__proto__', {
47-
id: 1,
48-
data: { title: 'bad' },
49-
previousData: { id: 1 },
50-
} as any)
51-
).rejects.toThrow('Invalid resource key: __proto__');
52-
});
53-
54-
it('does not corrupt local data when update targets an unknown id', async () => {
55-
(localforage.keys as jest.Mock).mockResolvedValue([
56-
'ra-data-local-forage-posts',
57-
]);
58-
(localforage.getItem as jest.Mock).mockResolvedValue([...posts]);
59-
const dataProvider = localForageDataProvider();
60-
61-
await expect(
62-
dataProvider.update('posts', {
63-
id: 3,
64-
data: { title: 'Updated' },
65-
previousData: { id: 3 },
66-
} as any)
67-
).rejects.toThrow('No item with identifier 3');
68-
69-
expect(localforage.setItem).not.toHaveBeenCalled();
70-
});
71-
72-
it('does not partially update local data when updateMany includes an unknown id', async () => {
73-
(localforage.keys as jest.Mock).mockResolvedValue([
74-
'ra-data-local-forage-posts',
75-
]);
76-
(localforage.getItem as jest.Mock).mockResolvedValue([...posts]);
77-
const dataProvider = localForageDataProvider();
78-
79-
await expect(
80-
dataProvider.updateMany('posts', {
81-
ids: [1, 3],
82-
data: { title: 'Updated' },
83-
} as any)
84-
).rejects.toThrow('No item with identifier 3');
85-
86-
expect(localforage.setItem).not.toHaveBeenCalled();
87-
});
88-
89-
it('does not corrupt local data when delete targets an unknown id', async () => {
90-
(localforage.keys as jest.Mock).mockResolvedValue([
91-
'ra-data-local-forage-posts',
92-
]);
93-
(localforage.getItem as jest.Mock).mockResolvedValue([...posts]);
94-
const dataProvider = localForageDataProvider();
95-
96-
await expect(
97-
dataProvider.delete('posts', {
98-
id: 3,
99-
previousData: { id: 3 },
100-
} as any)
101-
).rejects.toThrow('No item with identifier 3');
102-
103-
expect(localforage.setItem).not.toHaveBeenCalled();
104-
});
105-
106-
it('does not partially delete local data when deleteMany includes an unknown id', async () => {
107-
(localforage.keys as jest.Mock).mockResolvedValue([
108-
'ra-data-local-forage-posts',
109-
]);
110-
(localforage.getItem as jest.Mock).mockResolvedValue([...posts]);
111-
const dataProvider = localForageDataProvider();
112-
113-
await expect(
114-
dataProvider.deleteMany('posts', {
115-
ids: [1, 3],
116-
} as any)
117-
).rejects.toThrow('No item with identifier 3');
118-
119-
expect(localforage.setItem).not.toHaveBeenCalled();
120-
});
37+
it.each(['__proto__', 'constructor', 'prototype'])(
38+
'rejects unsafe resource key %s in update',
39+
async unsafeKey => {
40+
const dataProvider = localForageDataProvider();
41+
await expect(
42+
dataProvider.update(unsafeKey, {
43+
id: 1,
44+
data: { title: 'bad' },
45+
previousData: { id: 1 },
46+
} as any)
47+
).rejects.toThrow(`Invalid resource key: ${unsafeKey}`);
48+
}
49+
);
50+
51+
it.each(['__proto__', 'constructor', 'prototype'])(
52+
'rejects unsafe resource key %s in updateMany',
53+
async unsafeKey => {
54+
const dataProvider = localForageDataProvider();
55+
await expect(
56+
dataProvider.updateMany(unsafeKey, {
57+
ids: [1],
58+
data: { title: 'bad' },
59+
} as any)
60+
).rejects.toThrow(`Invalid resource key: ${unsafeKey}`);
61+
}
62+
);
63+
64+
it.each(['__proto__', 'constructor', 'prototype'])(
65+
'rejects unsafe resource key %s in create',
66+
async unsafeKey => {
67+
const dataProvider = localForageDataProvider();
68+
await expect(
69+
dataProvider.create(unsafeKey, {
70+
data: { title: 'bad' },
71+
} as any)
72+
).rejects.toThrow(`Invalid resource key: ${unsafeKey}`);
73+
}
74+
);
75+
76+
it.each(['__proto__', 'constructor', 'prototype'])(
77+
'rejects unsafe resource key %s in delete',
78+
async unsafeKey => {
79+
const dataProvider = localForageDataProvider();
80+
await expect(
81+
dataProvider.delete(unsafeKey, {
82+
id: 1,
83+
previousData: { id: 1 },
84+
} as any)
85+
).rejects.toThrow(`Invalid resource key: ${unsafeKey}`);
86+
}
87+
);
88+
89+
it.each(['__proto__', 'constructor', 'prototype'])(
90+
'rejects unsafe resource key %s in deleteMany',
91+
async unsafeKey => {
92+
const dataProvider = localForageDataProvider();
93+
await expect(
94+
dataProvider.deleteMany(unsafeKey, {
95+
ids: [1],
96+
} as any)
97+
).rejects.toThrow(`Invalid resource key: ${unsafeKey}`);
98+
}
99+
);
121100
});

packages/ra-data-local-storage/src/index.spec.ts

Lines changed: 63 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ import expect from 'expect';
33
import localStorageDataProvider from './index';
44

55
describe('ra-data-local-storage', () => {
6-
const posts = [
7-
{ id: 1, title: 'Hello world' },
8-
{ id: 2, title: 'Second post' },
9-
];
10-
116
beforeEach(() => {
127
localStorage.clear();
138
});
@@ -34,115 +29,67 @@ describe('ra-data-local-storage', () => {
3429
});
3530
});
3631

37-
it('rejects unsafe resource keys', () => {
38-
const dataProvider = localStorageDataProvider();
39-
40-
expect(() =>
41-
dataProvider.update('__proto__', {
42-
id: 1,
43-
data: { title: 'bad' },
44-
previousData: { id: 1 },
45-
} as any)
46-
).toThrow('Invalid resource key: __proto__');
47-
});
48-
49-
it('does not corrupt local data when update targets an unknown id', async () => {
50-
localStorage.setItem(
51-
'ra-data-local-storage-test',
52-
JSON.stringify({ posts })
53-
);
54-
const dataProvider = localStorageDataProvider({
55-
localStorageKey: 'ra-data-local-storage-test',
56-
localStorageUpdateDelay: 0,
57-
});
58-
59-
await expect(
60-
dataProvider.update('posts', {
61-
id: 3,
62-
data: { title: 'Updated' },
63-
previousData: { id: 3 },
64-
} as any)
65-
).rejects.toThrow('No item with identifier 3');
66-
await new Promise(resolve => setTimeout(resolve, 0));
67-
68-
expect(
69-
JSON.parse(
70-
localStorage.getItem('ra-data-local-storage-test') || '{}'
71-
)
72-
).toEqual({ posts });
73-
});
74-
75-
it('does not partially update local data when updateMany includes an unknown id', async () => {
76-
localStorage.setItem(
77-
'ra-data-local-storage-test',
78-
JSON.stringify({ posts })
79-
);
80-
const dataProvider = localStorageDataProvider({
81-
localStorageKey: 'ra-data-local-storage-test',
82-
localStorageUpdateDelay: 0,
83-
});
84-
85-
await expect(
86-
dataProvider.updateMany('posts', {
87-
ids: [1, 3],
88-
data: { title: 'Updated' },
89-
} as any)
90-
).rejects.toThrow('No item with identifier 3');
91-
await new Promise(resolve => setTimeout(resolve, 0));
92-
93-
expect(
94-
JSON.parse(
95-
localStorage.getItem('ra-data-local-storage-test') || '{}'
96-
)
97-
).toEqual({ posts });
98-
});
99-
100-
it('does not corrupt local data when delete targets an unknown id', async () => {
101-
localStorage.setItem(
102-
'ra-data-local-storage-test',
103-
JSON.stringify({ posts })
104-
);
105-
const dataProvider = localStorageDataProvider({
106-
localStorageKey: 'ra-data-local-storage-test',
107-
localStorageUpdateDelay: 0,
108-
});
109-
110-
await expect(
111-
dataProvider.delete('posts', {
112-
id: 3,
113-
previousData: { id: 3 },
114-
} as any)
115-
).rejects.toThrow('No item with identifier 3');
116-
await new Promise(resolve => setTimeout(resolve, 0));
117-
118-
expect(
119-
JSON.parse(
120-
localStorage.getItem('ra-data-local-storage-test') || '{}'
121-
)
122-
).toEqual({ posts });
123-
});
124-
125-
it('does not partially delete local data when deleteMany includes an unknown id', async () => {
126-
localStorage.setItem(
127-
'ra-data-local-storage-test',
128-
JSON.stringify({ posts })
129-
);
130-
const dataProvider = localStorageDataProvider({
131-
localStorageKey: 'ra-data-local-storage-test',
132-
localStorageUpdateDelay: 0,
133-
});
134-
135-
await expect(
136-
dataProvider.deleteMany('posts', {
137-
ids: [1, 3],
138-
} as any)
139-
).rejects.toThrow('No item with identifier 3');
140-
await new Promise(resolve => setTimeout(resolve, 0));
141-
142-
expect(
143-
JSON.parse(
144-
localStorage.getItem('ra-data-local-storage-test') || '{}'
145-
)
146-
).toEqual({ posts });
147-
});
32+
it.each(['__proto__', 'constructor', 'prototype'])(
33+
'rejects unsafe resource key %s in update',
34+
unsafeKey => {
35+
const dataProvider = localStorageDataProvider();
36+
expect(() =>
37+
dataProvider.update(unsafeKey, {
38+
id: 1,
39+
data: { title: 'bad' },
40+
previousData: { id: 1 },
41+
} as any)
42+
).toThrow(`Invalid resource key: ${unsafeKey}`);
43+
}
44+
);
45+
46+
it.each(['__proto__', 'constructor', 'prototype'])(
47+
'rejects unsafe resource key %s in updateMany',
48+
unsafeKey => {
49+
const dataProvider = localStorageDataProvider();
50+
expect(() =>
51+
dataProvider.updateMany(unsafeKey, {
52+
ids: [1],
53+
data: { title: 'bad' },
54+
} as any)
55+
).toThrow(`Invalid resource key: ${unsafeKey}`);
56+
}
57+
);
58+
59+
it.each(['__proto__', 'constructor', 'prototype'])(
60+
'rejects unsafe resource key %s in create',
61+
unsafeKey => {
62+
const dataProvider = localStorageDataProvider();
63+
expect(() =>
64+
dataProvider.create(unsafeKey, {
65+
data: { title: 'bad' },
66+
} as any)
67+
).toThrow(`Invalid resource key: ${unsafeKey}`);
68+
}
69+
);
70+
71+
it.each(['__proto__', 'constructor', 'prototype'])(
72+
'rejects unsafe resource key %s in delete',
73+
unsafeKey => {
74+
const dataProvider = localStorageDataProvider();
75+
expect(() =>
76+
dataProvider.delete(unsafeKey, {
77+
id: 1,
78+
previousData: { id: 1 },
79+
} as any)
80+
).toThrow(`Invalid resource key: ${unsafeKey}`);
81+
}
82+
);
83+
84+
it.each(['__proto__', 'constructor', 'prototype'])(
85+
'rejects unsafe resource key %s in deleteMany',
86+
unsafeKey => {
87+
const dataProvider = localStorageDataProvider();
88+
expect(() =>
89+
dataProvider.deleteMany(unsafeKey, {
90+
ids: [1],
91+
} as any)
92+
).toThrow(`Invalid resource key: ${unsafeKey}`);
93+
}
94+
);
14895
});

0 commit comments

Comments
 (0)