Compare commits

...
Author SHA1 Message Date
William Schurman fa4e2484c9 fix: fix null handling in load paths 2020-11-16 12:39:16 -08:00
11 changed files with 183 additions and 31 deletions

No files matched your search

+2 -2
View File
@@ -79,7 +79,7 @@ export default class EnforcingEntityLoader<
uniqueFieldName,
fieldValue
);
return entityResult ? entityResult.enforceValue() : null;
return entityResult.enforceValue();
}
/**
@@ -98,7 +98,7 @@ export default class EnforcingEntityLoader<
*/
async loadByIDNullableAsync(id: TID): Promise<TEntity | null> {
const entityResult = await this.entityLoader.loadByIDNullableAsync(id);
return entityResult ? entityResult.enforceValue() : null;
return entityResult.enforceValue();
}
/**
+32 -15
View File
@@ -23,6 +23,7 @@ export default class EntityAssociationLoader<
* @param queryContext - query context in which to perform the load
*/
async loadAssociatedEntityAsync<
TIdentifyingField extends keyof Pick<TFields, TSelectedFields>,
TAssociatedFields,
TAssociatedID,
TAssociatedEntity extends ReadonlyEntity<
@@ -40,7 +41,7 @@ export default class EntityAssociationLoader<
>,
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
>(
fieldIdentifyingAssociatedEntity: keyof Pick<TFields, TSelectedFields>,
fieldIdentifyingAssociatedEntity: TIdentifyingField,
associatedEntityClass: IEntityClass<
TAssociatedFields,
TAssociatedID,
@@ -54,14 +55,20 @@ export default class EntityAssociationLoader<
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
.getQueryContextProvider()
.getQueryContext()
): Promise<Result<TAssociatedEntity>> {
): Promise<
Result<null extends TFields[TIdentifyingField] ? TAssociatedEntity | null : TAssociatedEntity>
> {
const associatedEntityID = this.entity.getField(fieldIdentifyingAssociatedEntity);
if (!associatedEntityID) {
return result(null) as any;
}
const loader = this.entity
.getViewerContext()
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
.getLoaderFactory()
.forLoad(queryContext);
return await loader.loadByIDAsync((associatedEntityID as unknown) as TAssociatedID);
return (await loader.loadByIDAsync((associatedEntityID as unknown) as TAssociatedID)) as any;
}
/**
@@ -127,6 +134,7 @@ export default class EntityAssociationLoader<
* @param queryContext - query context in which to perform the load
*/
async loadAssociatedEntityByFieldEqualingAsync<
TIdentifyingField extends keyof Pick<TFields, TSelectedFields>,
TAssociatedFields,
TAssociatedID,
TAssociatedEntity extends ReadonlyEntity<
@@ -144,7 +152,7 @@ export default class EntityAssociationLoader<
>,
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
>(
fieldIdentifyingAssociatedEntity: keyof Pick<TFields, TSelectedFields>,
fieldIdentifyingAssociatedEntity: TIdentifyingField,
associatedEntityClass: IEntityClass<
TAssociatedFields,
TAssociatedID,
@@ -159,8 +167,12 @@ export default class EntityAssociationLoader<
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
.getQueryContextProvider()
.getQueryContext()
): Promise<Result<TAssociatedEntity> | null> {
): Promise<Result<TAssociatedEntity | null>> {
const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity);
if (!associatedFieldValue) {
return result(null);
}
const loader = this.entity
.getViewerContext()
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
@@ -215,6 +227,10 @@ export default class EntityAssociationLoader<
.getQueryContext()
): Promise<readonly Result<TAssociatedEntity>[]> {
const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity);
if (!associatedFieldValue) {
return [];
}
const loader = this.entity
.getViewerContext()
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
@@ -258,7 +274,7 @@ export default class EntityAssociationLoader<
>
],
queryContext?: EntityQueryContext
): Promise<Result<TEntity2> | null>;
): Promise<Result<TEntity2 | null>>;
/**
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
@@ -313,7 +329,7 @@ export default class EntityAssociationLoader<
>
],
queryContext?: EntityQueryContext
): Promise<Result<TEntity3> | null>;
): Promise<Result<TEntity3 | null>>;
/**
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
@@ -389,7 +405,7 @@ export default class EntityAssociationLoader<
>
],
queryContext?: EntityQueryContext
): Promise<Result<TEntity4> | null>;
): Promise<Result<TEntity4 | null>>;
/**
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
@@ -400,12 +416,12 @@ export default class EntityAssociationLoader<
async loadAssociatedEntityThroughAsync(
loadDirectives: EntityLoadThroughDirective<TViewerContext, any, any, any, any, any, any, any>[],
queryContext?: EntityQueryContext
): Promise<Result<ReadonlyEntity<any, any, any, any>> | null>;
): Promise<Result<ReadonlyEntity<any, any, any, any> | null>>;
async loadAssociatedEntityThroughAsync(
loadDirectives: EntityLoadThroughDirective<TViewerContext, any, any, any, any, any, any, any>[],
queryContext?: EntityQueryContext
): Promise<Result<ReadonlyEntity<any, any, any, any>> | null> {
): Promise<Result<ReadonlyEntity<any, any, any, any> | null>> {
let currentEntity: ReadonlyEntity<any, any, any, any> = this.entity;
for (const loadDirective of loadDirectives) {
const {
@@ -413,7 +429,7 @@ export default class EntityAssociationLoader<
fieldIdentifyingAssociatedEntity,
associatedEntityLookupByField,
} = loadDirective;
let associatedEntityResult: Result<ReadonlyEntity<any, any, any, any>> | null;
let associatedEntityResult: Result<ReadonlyEntity<any, any, any, any> | null>;
if (associatedEntityLookupByField) {
associatedEntityResult = await currentEntity
.associationLoader()
@@ -433,13 +449,14 @@ export default class EntityAssociationLoader<
);
}
if (!associatedEntityResult) {
return null;
}
if (!associatedEntityResult.ok) {
return result(associatedEntityResult.reason);
}
if (!associatedEntityResult.value) {
return result(null);
}
currentEntity = associatedEntityResult.value;
}
return result(currentEntity);
+3 -3
View File
@@ -132,13 +132,13 @@ export default class EntityLoader<
async loadByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
uniqueFieldName: N,
fieldValue: NonNullable<TFields[N]>
): Promise<Result<TEntity> | null> {
): Promise<Result<TEntity | null>> {
const entityResults = await this.loadManyByFieldEqualingAsync(uniqueFieldName, fieldValue);
invariant(
entityResults.length <= 1,
`loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${uniqueFieldName}=${fieldValue}`
);
return entityResults[0] ?? null;
return entityResults[0] ?? result(null);
}
/**
@@ -160,7 +160,7 @@ export default class EntityLoader<
* @param id - ID of the entity
* @returns entity result for matching ID, or null if no entity exists for ID.
*/
async loadByIDNullableAsync(id: TID): Promise<Result<TEntity> | null> {
async loadByIDNullableAsync(id: TID): Promise<Result<TEntity | null>> {
return await this.loadByFieldEqualingAsync(this.idField, id as any);
}
@@ -9,7 +9,7 @@ import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUn
describe(EntityAssociationLoader, () => {
describe('loadAssociatedEntityAsync', () => {
it('loads associated entities by ID', async () => {
it('loads associated entities by ID and correctly handles a null value', async () => {
const companionProvider = createUnitTestEntityCompanionProvider();
const viewerContext = new TestViewerContext(companionProvider);
const testOtherEntity = await enforceAsyncResult(
@@ -24,6 +24,11 @@ describe(EntityAssociationLoader, () => {
testEntity.associationLoader().loadAssociatedEntityAsync('stringField', TestEntity)
);
expect(loadedOther.getID()).toEqual(testOtherEntity.getID());
const loadedOther2 = await enforceAsyncResult(
testEntity.associationLoader().loadAssociatedEntityAsync('nullableField', TestEntity)
);
expect(loadedOther2).toBeNull();
});
});
@@ -62,7 +67,7 @@ describe(EntityAssociationLoader, () => {
const loadedOtherResult = await testEntity
.associationLoader()
.loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
expect(loadedOtherResult?.enforceValue().getID()).toEqual(testOtherEntity.getID());
expect(loadedOtherResult.enforceValue()?.getID()).toEqual(testOtherEntity.getID());
});
it('returns null when loading associated entities by field equaling a non existent association', async () => {
@@ -74,7 +79,19 @@ describe(EntityAssociationLoader, () => {
const loadedOtherResult = await testEntity
.associationLoader()
.loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
expect(loadedOtherResult).toBeNull();
expect(loadedOtherResult.enforceValue()).toBeNull();
});
it('returns null when load-by field is null', async () => {
const companionProvider = createUnitTestEntityCompanionProvider();
const viewerContext = new TestViewerContext(companionProvider);
const testEntity = await enforceAsyncResult(
TestEntity.creator(viewerContext).setField('stringField', 'blah').createAsync()
);
const loadedOtherResult = await testEntity
.associationLoader()
.loadAssociatedEntityByFieldEqualingAsync('nullableField', TestEntity, 'customIdField');
expect(loadedOtherResult.enforceValue()).toBeNull();
});
});
@@ -102,6 +119,22 @@ describe(EntityAssociationLoader, () => {
expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
expect(loaded.find((e) => e.getID() === testOtherEntity2.getID())).not.toBeUndefined();
});
it('returns empty results when field being queried by is null', async () => {
const companionProvider = createUnitTestEntityCompanionProvider();
const viewerContext = new TestViewerContext(companionProvider);
const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync());
const loaded = await enforceResultsAsync(
testEntity
.associationLoader()
.loadManyAssociatedEntitiesByFieldEqualingAsync(
'nullableField',
TestEntity,
'stringField'
)
);
expect(loaded).toHaveLength(0);
});
});
describe('loadAssociatedEntityThroughAsync', () => {
@@ -127,7 +160,7 @@ describe(EntityAssociationLoader, () => {
fieldIdentifyingAssociatedEntity: 'foreignKey',
},
]);
expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID());
expect(loaded2Result.enforceValue()?.getID()).toEqual(testEntity2.getID());
const loaded3Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
{
@@ -139,7 +172,7 @@ describe(EntityAssociationLoader, () => {
fieldIdentifyingAssociatedEntity: 'testIndexedField',
},
]);
expect(loaded3Result?.enforceValue().getID()).toEqual(testEntity3.getID());
expect(loaded3Result.enforceValue()?.getID()).toEqual(testEntity3.getID());
const loaded4Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
{
@@ -155,7 +188,7 @@ describe(EntityAssociationLoader, () => {
fieldIdentifyingAssociatedEntity: 'foreignKey',
},
]);
expect(loaded4Result?.enforceValue().getID()).toEqual(testEntity4.getID());
expect(loaded4Result.enforceValue()?.getID()).toEqual(testEntity4.getID());
});
it('fails when chain loading associated entity fails', async () => {
@@ -193,7 +226,7 @@ describe(EntityAssociationLoader, () => {
associatedEntityLookupByField: 'stringField',
},
]);
expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID());
expect(loaded2Result.enforceValue()?.getID()).toEqual(testEntity2.getID());
});
it('returns null when chain loading by field equality returns null', async () => {
@@ -211,7 +244,24 @@ describe(EntityAssociationLoader, () => {
associatedEntityLookupByField: 'stringField',
},
]);
expect(loaded2Result).toBeNull();
expect(loaded2Result.enforceValue()).toBeNull();
});
it('returns null when chain loading by field is null', async () => {
const companionProvider = createUnitTestEntityCompanionProvider();
const viewerContext = new TestViewerContext(companionProvider);
const testEntity = await enforceAsyncResult(
TestEntity.creator(viewerContext).setField('nullableField', null).createAsync()
);
const loadedResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
{
associatedEntityClass: TestEntity,
fieldIdentifyingAssociatedEntity: 'nullableField',
},
]);
expect(loadedResult.enforceValue()).toBeNull();
});
});
});
@@ -36,6 +36,7 @@ describe(EntityLoader, () => {
numberField: 5,
stringField: 'huh',
dateField: dateToInsert,
nullableField: null,
},
{
customIdField: 'world',
@@ -43,6 +44,7 @@ describe(EntityLoader, () => {
numberField: 3,
stringField: 'huh',
dateField: dateToInsert,
nullableField: null,
},
],
],
@@ -79,16 +81,16 @@ describe(EntityLoader, () => {
const entityResultNumber3 = await entityLoader.loadByFieldEqualingAsync('numberField', 3);
expect(entityResultNumber3).not.toBeNull();
expect(entityResultNumber3!.enforceValue().getID()).toEqual('world');
expect(entityResultNumber3.enforceValue()?.getID()).toEqual('world');
const entityResultNumber4 = await entityLoader.loadByFieldEqualingAsync('numberField', 4);
expect(entityResultNumber4).toBeNull();
expect(entityResultNumber4.enforceValue()).toBeNull();
await expect(entityLoader.loadByFieldEqualingAsync('stringField', 'huh')).rejects.toThrowError(
'loadByFieldEqualing: Multiple entities of type TestEntity found for stringField=huh'
);
await expect(entityLoader.loadByIDNullableAsync('fake')).resolves.toBeNull();
expect((await entityLoader.loadByIDNullableAsync('fake')).enforceValue()).toBeNull();
await expect(entityLoader.loadByIDNullableAsync('hello')).resolves.not.toBeNull();
});
@@ -112,6 +114,7 @@ describe(EntityLoader, () => {
numberField: 4,
testIndexedField: '4',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -119,6 +122,7 @@ describe(EntityLoader, () => {
numberField: 4,
testIndexedField: '5',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'blah',
@@ -126,6 +130,7 @@ describe(EntityLoader, () => {
numberField: 4,
testIndexedField: '6',
dateField: new Date(),
nullableField: null,
},
],
],
@@ -189,6 +194,7 @@ describe(EntityLoader, () => {
testIndexedField: '1',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
],
],
@@ -310,6 +310,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -317,6 +318,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '5',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
]);
const newEntity = await entityMutatorFactory
@@ -336,6 +338,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -343,6 +346,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '5',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
]);
@@ -372,6 +376,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -379,6 +384,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '5',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
]);
@@ -409,6 +415,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -416,6 +423,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '5',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
]);
@@ -441,6 +449,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -448,6 +457,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -484,6 +494,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -491,6 +502,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -528,6 +540,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -535,6 +548,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -573,6 +587,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -580,6 +595,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '4',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -609,6 +625,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -640,6 +657,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -674,6 +692,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -709,6 +728,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -734,6 +754,7 @@ describe(EntityMutatorFactory, () => {
testIndexedField: '3',
numberField: 3,
dateField: new Date(),
nullableField: null,
},
]);
@@ -63,6 +63,7 @@ describe(ReadonlyEntity, () => {
stringField: '3',
numberField: 4,
dateField: new Date(),
nullableField: null,
});
expect(testEntity.getUniqueIdentifier()).not.toEqual(testEntity2.getUniqueIdentifier());
});
@@ -103,6 +103,15 @@ export default class EntityDataManager<TFields> {
fieldName: N,
fieldValues: readonly NonNullable<TFields[N]>[]
): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>> {
const nullOrUndefinedValueIndex = fieldValues.findIndex(
(value) => value === null || value === undefined
);
if (nullOrUndefinedValueIndex >= 0) {
throw new Error(
`Invalid load: ${this.entityClassName} (${fieldName} = ${fieldValues[nullOrUndefinedValueIndex]})`
);
}
// don't cache when in transaction, as rollbacks complicate things significantly
if (queryContext.isInTransaction()) {
return await this.databaseAdapter.fetchManyWhereAsync(queryContext, fieldName, fieldValues);
@@ -36,6 +36,7 @@ const getObjects = (): Map<string, TestFields[]> =>
stringField: 'hello',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
{
customIdField: '2',
@@ -43,6 +44,7 @@ const getObjects = (): Map<string, TestFields[]> =>
stringField: 'hello',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
{
customIdField: '3',
@@ -50,6 +52,7 @@ const getObjects = (): Map<string, TestFields[]> =>
stringField: 'world',
numberField: 1,
dateField: new Date(),
nullableField: null,
},
],
],
@@ -566,4 +569,34 @@ describe(EntityDataManager, () => {
verify(metricsAdapterMock.incrementDataManagerCacheLoadCount(anyNumber())).never();
verify(metricsAdapterMock.incrementDataManagerDatabaseLoadCount(anyNumber())).never();
});
it('throws when a load by value is null or undefined', async () => {
const objects = getObjects();
const dataStore = StubDatabaseAdapter.convertFieldObjectsToDataStore(
testEntityConfiguration,
objects
);
const databaseAdapter = new StubDatabaseAdapter<TestFields>(testEntityConfiguration, dataStore);
const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
const entityDataManager = new EntityDataManager(
databaseAdapter,
entityCache,
StubQueryContextProvider,
new NoOpEntityMetricsAdapter(),
TestEntity.name
);
const queryContext = StubQueryContextProvider.getQueryContext();
await expect(
entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'nullableField', [null as any])
).rejects.toThrowError('Invalid load: TestEntity (nullableField = null)');
await expect(
entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'nullableField', [
undefined as any,
])
).rejects.toThrowError('Invalid load: TestEntity (nullableField = undefined)');
});
});
@@ -18,6 +18,7 @@ export type TestFields = {
stringField: string;
numberField: number;
dateField: Date;
nullableField: string | null;
};
export const testEntityConfiguration = new EntityConfiguration<TestFields>({
@@ -40,6 +41,9 @@ export const testEntityConfiguration = new EntityConfiguration<TestFields>({
dateField: new DateField({
columnName: 'date_field',
}),
nullableField: new StringField({
columnName: 'nullable_field',
}),
},
databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES,
cacheAdapterFlavor: CacheAdapterFlavor.REDIS,
@@ -88,6 +92,7 @@ export default class TestEntity extends Entity<TestFields, string, ViewerContext
stringField: 'hello',
numberField: 1,
dateField: new Date(),
nullableField: null,
})
);
}
@@ -35,6 +35,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 5,
stringField: 'huh',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -42,6 +43,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'wat',
dateField: new Date(),
nullableField: null,
},
],
],
@@ -73,6 +75,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'a',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -80,6 +83,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'b',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -87,6 +91,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'c',
dateField: new Date(),
nullableField: null,
},
],
],
@@ -138,6 +143,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'a',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -145,6 +151,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'b',
dateField: new Date(),
nullableField: null,
},
{
customIdField: 'world',
@@ -152,6 +159,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'c',
dateField: new Date(),
nullableField: null,
},
],
],
@@ -236,6 +244,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'a',
dateField: new Date(),
nullableField: null,
},
],
],
@@ -269,6 +278,7 @@ describe(StubDatabaseAdapter, () => {
numberField: 3,
stringField: 'a',
dateField: new Date(),
nullableField: null,
},
],
],