Skip to content

Commit 3b5f66a

Browse files
committed
types.test.ts: replace ThrowingConverter with fakeConverter() and add neverCall() function.
1 parent 101a889 commit 3b5f66a

File tree

1 file changed

+65
-62
lines changed

1 file changed

+65
-62
lines changed

packages/firestore/test/unit/lite-api/types.test.ts

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -696,78 +696,81 @@ describe('FirestoreTypeConverter', () => {
696696
}
697697
});
698698

699-
it('setDoc() fails to compile if `data` argument is missing properties', () => {
700-
async function _(docRef: DocumentReference): Promise<void> {
701-
const converter = new ThrowingConverter<
702-
{ foo: string },
703-
{ bar: number }
704-
>();
699+
it('setDoc() fails to compile if AppModelType argument is missing properties', () =>
700+
neverCall(async docRef => {
701+
const converter = fakeConverter<{ foo: string }, {}>();
705702
const docRefWithConverter = docRef.withConverter(converter);
706-
// @ts-expect-error `data` argument is missing `foo` property.
707-
await setDoc(docRefWithConverter, { bar: 42 });
708-
}
709-
});
703+
// @ts-expect-error The `foo` property declared in AppModelType is missing.
704+
await setDoc(docRefWithConverter, {});
705+
}));
710706

711-
it('setDoc() fails to compile if `data` argument has incorrect type for a property', () => {
712-
async function _(docRef: DocumentReference): Promise<void> {
713-
const converter = new ThrowingConverter<{ foo: string }, {}>();
707+
it('setDoc() fails to compile if AppModelType argument contains undeclared properties', () =>
708+
neverCall(async docRef => {
709+
const converter = fakeConverter<{ foo: string }, { bar: number }>();
714710
const docRefWithConverter = docRef.withConverter(converter);
715-
// @ts-expect-error The `data` argument has the wrong type for `foo`.
711+
// @ts-expect-error The `bar` property is not declared in AppModelType.
712+
await setDoc(docRefWithConverter, { foo: 'foo', bar: 42 });
713+
}));
714+
715+
it('setDoc() fails to compile if AppModelType argument contains a property with an incorrect type', () =>
716+
neverCall(async docRef => {
717+
const converter = fakeConverter<{ foo: string }, { foo: number }>();
718+
const docRefWithConverter = docRef.withConverter(converter);
719+
// @ts-expect-error The `foo` property is declared as `string` in
720+
// AppModelType, but a `number` is specified.
716721
await setDoc(docRefWithConverter, { foo: 42 });
717-
}
718-
});
722+
}));
719723

720-
it('updateDoc() fails to compile if `data` argument is missing properties', () => {
721-
async function _(docRef: DocumentReference): Promise<void> {
722-
const converter = new ThrowingConverter<
723-
{ foo: string },
724-
{ bar: number }
725-
>();
724+
it('updateDoc() successfully compiles even if DbModelType argument is missing properties', () =>
725+
neverCall(async docRef => {
726+
const converter = fakeConverter<{ foo: string }, { bar: number }>();
726727
const docRefWithConverter = docRef.withConverter(converter);
727-
// @ts-expect-error `data` argument is missing `bar` property.
728-
await updateDoc(docRefWithConverter, { foo: 'foo' });
729-
}
730-
});
728+
await updateDoc(docRefWithConverter, {});
729+
}));
731730

732-
it('updateDoc() fails to compile if `data` argument has incorrect type for a property', () => {
733-
async function _(docRef: DocumentReference): Promise<void> {
734-
const converter = new ThrowingConverter<{}, { bar: number }>();
731+
it('updateDoc() fails to compile if DbModelType argument contains undeclared properties', () =>
732+
neverCall(async docRef => {
733+
const converter = fakeConverter<{ foo: string }, { bar: number }>();
735734
const docRefWithConverter = docRef.withConverter(converter);
736-
// @ts-expect-error The `data` argument has the wrong type for `bar`.
737-
await updateDoc(docRefWithConverter, { bar: 'bar' });
738-
}
739-
});
735+
// @ts-expect-error The `foo` property is not declared in DbModelType.
736+
await updateDoc(docRefWithConverter, { foo: 'foo', bar: 42 });
737+
}));
740738

741-
it('getDoc() returns AppModelType', () => {
742-
async function _(docRef: DocumentReference): Promise<void> {
743-
const converter = new ThrowingConverter<
744-
{ foo: string },
745-
{ bar: number }
746-
>();
739+
it('updateDoc() fails to compile if DbModelType argument contains a property with an incorrect type', () =>
740+
neverCall(async docRef => {
741+
const converter = fakeConverter<{ foo: string }, { foo: number }>();
742+
const docRefWithConverter = docRef.withConverter(converter);
743+
// @ts-expect-error The `foo` property is declared as `number` in
744+
// DbModelType, but a `string` is specified.
745+
await updateDoc(docRefWithConverter, { foo: 'foo' });
746+
}));
747+
748+
it('getDoc() returns AppModelType', () =>
749+
neverCall<Promise<{ foo: string }>>(async docRef => {
750+
const converter = fakeConverter<{ foo: string }, { bar: number }>();
747751
const docRefWithConverter = docRef.withConverter(converter);
748752
const snapshot = await getDoc(docRefWithConverter);
749-
const data: { foo: string } = snapshot.data()!;
750-
expect(data.foo).to.equal('foo');
751-
}
752-
});
753+
return snapshot.data()!;
754+
}));
755+
});
753756

754-
/**
755-
* An implementation of FirestoreDataConverter whose methods simply throw an
756-
* exception. Instances of this class may be useful for tests that only desire
757-
* to check the compile-time type checking but not actually invoke the
758-
* converter at runtime.
759-
*/
760-
class ThrowingConverter<AppModelType, DbModelType extends DocumentData>
761-
implements FirestoreDataConverter<AppModelType, DbModelType>
762-
{
763-
toFirestore(
764-
modelObject: WithFieldValue<AppModelType>
765-
): WithFieldValue<DbModelType> {
766-
throw new Error('ThrowingConverter.toFirestore() should not be called');
767-
}
757+
/**
758+
* Does nothing; however, this function can be useful in tests that only check
759+
* the compile-time behavior of the TypeScript compiler. For example, a test
760+
* that ensures that a certain statement successfully compiles could pass the
761+
* code block to this function to exercise the compiler but the code will not
762+
* actually be executed at runtime.
763+
*/
764+
function neverCall<T>(_: (docRef: DocumentReference) => T): void {}
768765

769-
fromFirestore(snapshot: QueryDocumentSnapshot): AppModelType {
770-
throw new Error('ThrowingConverter.fromFirestore() should not be called');
771-
}
772-
}
773-
});
766+
/**
767+
* Does nothing; this function does not actually exist but is merely _declared_
768+
* to exist. This facilitates creating variables typed as FirestoreDataConverter
769+
* with the given type parameters at compile time. This can be useful in tests
770+
* that only check compile-time behavior of the TypeScript compiler but don't
771+
* actually get executed at runtime.
772+
*/
773+
declare function fakeConverter<
774+
AppModelType,
775+
DbModelType extends DocumentData
776+
>(): FirestoreDataConverter<AppModelType, DbModelType>;

0 commit comments

Comments
 (0)