Skip to content
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

CB-3898 add base CachedMapResource tests #2013

Merged
merged 10 commits into from
Sep 26, 2023
26 changes: 14 additions & 12 deletions webapp/packages/core-sdk/src/Resource/CachedDataResource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ interface ILoaderData {
value: number;
}

const DEFAULT_STATE: () => ILoaderData[] = () => [];

const LOADER_DATA_MOCK: ILoaderData[] = [
{
id: '1',
Expand All @@ -23,21 +25,21 @@ const LOADER_DATA_MOCK: ILoaderData[] = [
},
];

async function fetchMock(): Promise<ILoaderData[]> {
return new Promise(resolve => {
setTimeout(() => {
resolve(LOADER_DATA_MOCK);
}, 1);
});
}

class TestDataResource extends CachedDataResource<ILoaderData[]> {
constructor() {
super(() => []);
}

private async fetchFromAPI(): Promise<ILoaderData[]> {
return new Promise(resolve => {
setTimeout(() => {
resolve(LOADER_DATA_MOCK);
}, 1);
});
super(DEFAULT_STATE);
}

protected async loader() {
const data = await this.fetchFromAPI();
const data = await fetchMock();
return data;
}
}
Expand All @@ -53,8 +55,8 @@ describe('CachedDataResource', () => {
expect(dataResource).toBeInstanceOf(CachedDataResource);
});

test('should initialize with an empty array', () => {
expect(dataResource.data).toEqual([]);
test('should initialize with the default state', () => {
expect(dataResource.data).toEqual(DEFAULT_STATE());
});

test('should load data', async () => {
Expand Down
75 changes: 37 additions & 38 deletions webapp/packages/core-sdk/src/Resource/CachedMapResource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { toJS } from 'mobx';

import { CachedMapResource } from './CachedMapResource';
import type { ResourceKey } from './ResourceKey';
import { resourceKeyList } from './ResourceKeyList';

interface ILoaderData {
interface IEntityData {
id: string;
value: number;
}

const ERROR_ITEM_ID = 'error';

const LOADER_DATA_MOCK: ILoaderData[] = [
const DATA_MOCK: IEntityData[] = [
{
id: '1',
Wroud marked this conversation as resolved.
Show resolved Hide resolved
value: 1,
Expand All @@ -32,41 +34,34 @@ const LOADER_DATA_MOCK: ILoaderData[] = [
];

const TEST_ERROR_MESSAGE = 'Test error';
const DEFAULT_STATE = () => new Map();

async function fetchMock(key: ResourceKey<string> | undefined): Promise<IEntityData[]> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (key) {
if (key === ERROR_ITEM_ID) {
reject(new Error(TEST_ERROR_MESSAGE));
}

class TestMapResource extends CachedMapResource<string, ILoaderData> {
constructor() {
super();
}

async fetchAnError() {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(TEST_ERROR_MESSAGE));
}, 1);
});
}

private async fetchFromAPI(key: ResourceKey<string> | undefined): Promise<ILoaderData[]> {
return new Promise(resolve => {
setTimeout(() => {
if (key) {
const data = LOADER_DATA_MOCK.find(d => d.id === key);
if (data) {
resolve([data]);
}
} else {
resolve(LOADER_DATA_MOCK);
const data = DATA_MOCK.find(d => d.id === key);
if (data) {
resolve([data]);
}
}, 1);
});
} else {
resolve(DATA_MOCK);
}
}, 1);
});
}

class TestMapResource extends CachedMapResource<string, IEntityData> {
constructor() {
super(DEFAULT_STATE);
}

protected async loader(key: ResourceKey<string>) {
if (key === ERROR_ITEM_ID) {
await this.fetchAnError();
}

const data = await this.fetchFromAPI(key);
const data = await fetchMock(key);
this.replace(resourceKeyList(data.map(d => d.id)), data);
return this.data;
}
Expand All @@ -87,6 +82,10 @@ describe('CachedMapResource', () => {
expect(mapResource).toBeInstanceOf(CachedMapResource);
});

test('should initialize with the initial value', () => {
expect(toJS(mapResource.data)).toEqual(DEFAULT_STATE());
});

test('should return all entries', () => {
mapResource.set('key1', { id: 'key1', value: 1 });
mapResource.set('key2', { id: 'key2', value: 2 });
Expand All @@ -111,10 +110,6 @@ describe('CachedMapResource', () => {
expect(mapResource.keys).toEqual(['key1', 'key2']);
});

test('should initialize with an empty map', () => {
expect(mapResource.entries).toEqual([]);
});

test('should load data for a specific key', async () => {
await mapResource.load('1');
expect(mapResource.get('1')).toEqual({ id: '1', value: 1 });
Expand All @@ -126,7 +121,7 @@ describe('CachedMapResource', () => {
expect(mapResource.get(ERROR_ITEM_ID)).toBeUndefined();
});

test('should change loaded state when data is loaded ', async () => {
test('should mark loaded data as loaded', async () => {
await mapResource.load('1');
expect(mapResource.isLoaded('1')).toBe(true);
});
Expand All @@ -151,13 +146,17 @@ describe('CachedMapResource', () => {
test('should replace multiple keys', () => {
mapResource.set('key1', { id: 'key1', value: 1 });
mapResource.set('key2', { id: 'key2', value: 2 });
mapResource.set('key4', { id: 'key4', value: 4 });

mapResource.replace(resourceKeyList(['key1', 'key3']), [
{ id: 'key1', value: 11 },
{ id: 'key3', value: 33 },
]);

expect(mapResource.get('key1')).toStrictEqual({ id: 'key1', value: 11 });
expect(mapResource.get('key2')).toBeUndefined();
expect(mapResource.get('key3')).toStrictEqual({ id: 'key3', value: 33 });
expect(mapResource.data.size).toBe(2);
});

test('should outdated certain keys', () => {
Expand Down Expand Up @@ -215,7 +214,7 @@ describe('CachedMapResource', () => {
expect(handler).toHaveBeenCalled();
});

test('should run onItemUpdate handlers on data delete', () => {
test('should run onItemUpdate handlers on item update', () => {
const handler = jest.fn();

mapResource.set('key1', { id: 'key1', value: 1 });
Expand Down
Loading