Skip to content

Commit

Permalink
chore: export adapter types, fix adapter test arrangements (#332)
Browse files Browse the repository at this point in the history
* Export adapter types

* Cleanup

* Snapshot

* export

* Revert
  • Loading branch information
charlesfries authored Feb 20, 2025
1 parent aea8e34 commit d26033f
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 49 deletions.
26 changes: 14 additions & 12 deletions addon/adapters/cloud-firestore-modular.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { Snapshot as _Snapshot } from '@ember-data/legacy-compat/legacy-net
import type { SnapshotRecordArray as _SnapshotRecordArray } from '@ember-data/legacy-compat/-private';
import type { Collection } from '@ember-data/store/-private/record-arrays/identifier-array';
import type {
LegacyBelongsToField,
LegacyHasManyField,
LegacyBelongsToField as _LegacyBelongsToField,
LegacyHasManyField as _LegacyHasManyField,
} from '@warp-drive/core-types/schema/fields';
import type Model from 'ember-data/model';
import RSVP from 'rsvp';
Expand Down Expand Up @@ -48,19 +48,21 @@ export interface AdapterOption {
[key: string]: unknown;
}

interface Snapshot extends _Snapshot {
export interface Snapshot extends _Snapshot {
adapterOptions: AdapterOption;
}

interface SnapshotRecordArray extends _SnapshotRecordArray {
export interface SnapshotRecordArray extends _SnapshotRecordArray {
adapterOptions: AdapterOption;
}

type BelongsToRelationshipMeta = LegacyBelongsToField & {
options: { isRealtime?: boolean };
export type LegacyBelongsToField = _LegacyBelongsToField & {
options: {
isRealtime?: boolean;
};
};

type HasManyRelationshipMeta = LegacyHasManyField & {
export type LegacyHasManyField = _LegacyHasManyField & {
key: string;
options: {
isRealtime?: boolean;
Expand All @@ -82,9 +84,9 @@ export default class CloudFirestoreAdapter extends Adapter {
return !!fastboot && fastboot.isFastBoot;
}

public generateIdForRecord(_store: Store, type: unknown): string {
public generateIdForRecord(_store: Store, type: string): string {
const db = getFirestore();
const collectionName = buildCollectionName(type as string); // TODO: EmberData types incorrect
const collectionName = buildCollectionName(type);

return doc(collection(db, collectionName)).id;
}
Expand Down Expand Up @@ -268,7 +270,7 @@ export default class CloudFirestoreAdapter extends Adapter {
_store: Store,
_snapshot: Snapshot,
url: string,
relationship: BelongsToRelationshipMeta,
relationship: LegacyBelongsToField,
): Promise<AdapterPayload> {
return new RSVP.Promise(async (resolve, reject) => {
try {
Expand Down Expand Up @@ -307,7 +309,7 @@ export default class CloudFirestoreAdapter extends Adapter {
store: Store,
snapshot: Snapshot,
url: string,
relationship: HasManyRelationshipMeta,
relationship: LegacyHasManyField,
): Promise<AdapterPayload> {
return new RSVP.Promise(async (resolve, reject) => {
try {
Expand Down Expand Up @@ -391,7 +393,7 @@ export default class CloudFirestoreAdapter extends Adapter {
store: Store,
snapshot: Snapshot,
url: string,
relationship: HasManyRelationshipMeta,
relationship: LegacyHasManyField,
): CollectionReference | Query {
const db = getFirestore();

Expand Down
3 changes: 3 additions & 0 deletions tests/dummy/app/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export default class UserModel extends Model {
@attr('number')
public declare age: number;

@attr('string')
public declare username: string;

@hasMany('group', { async: true, inverse: 'members' })
public declare groups: AsyncHasMany<GroupModel>;

Expand Down
84 changes: 47 additions & 37 deletions tests/unit/adapters/cloud-firestore-modular-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {
} from 'ember-cloud-firestore-adapter/firebase/firestore';
import type CloudFirestoreModularAdapter from 'ember-cloud-firestore-adapter/adapters/cloud-firestore-modular';
import AdapterRecordNotFoundError from 'ember-cloud-firestore-adapter/utils/custom-errors';
import type { Snapshot } from 'ember-cloud-firestore-adapter/adapters/cloud-firestore-modular';
import type UserModel from 'dummy/tests/dummy/app/models/user';
import resetFixtureData from '../../helpers/reset-fixture-data';

module('Unit | Adapter | cloud firestore modular', function (hooks) {
Expand Down Expand Up @@ -62,8 +64,14 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should proxy a call to updateRecord and return with the created doc', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const snapshot = { id: 'user_100', age: 30, username: 'user_100' };
const modelClass = store.modelFor('user');
const snapshot = store
.createRecord<UserModel>('user', {
id: 'user_100',
age: 30,
username: 'user_100',
})
._createSnapshot() as Snapshot;
const adapter = this.owner.lookup(
'adapter:cloud-firestore-modular',
) as CloudFirestoreModularAdapter;
Expand All @@ -73,16 +81,12 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
.returns(Promise.resolve({ foo: 'foo' }));

// Act
const result = await adapter.createRecord(
store,
modelClass,
snapshot as any,
);
const result = await adapter.createRecord(store, modelClass, snapshot);

// Assert
assert.deepEqual(result, { foo: 'foo' });
assert.ok(
updateRecordStub.calledWithExactly(store, modelClass, snapshot as any),
updateRecordStub.calledWithExactly(store, modelClass, snapshot),
);
});
});
Expand All @@ -91,11 +95,13 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should update record and resolve with the updated doc', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const snapshot = {
id: 'user_a',
age: 50,
};
const modelClass = store.modelFor('user');
const snapshot = store
.createRecord<UserModel>('user', {
id: 'user_a',
age: 50,
})
._createSnapshot() as Snapshot;
const adapter = this.owner.lookup(
'adapter:cloud-firestore-modular',
) as CloudFirestoreModularAdapter;
Expand All @@ -106,11 +112,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
});

// Act
const result = await adapter.updateRecord(
store,
modelClass,
snapshot as any,
);
const result = await adapter.updateRecord(store, modelClass, snapshot);

// Assert
assert.deepEqual(result, { age: 50, username: 'user_a' });
Expand All @@ -124,7 +126,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should update record in a custom collection and resolve with the updated resource', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const snapshot = {
id: 'user_a',
age: 50,
Expand Down Expand Up @@ -158,7 +160,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should update record and process additional batched writes', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const snapshot = {
id: 'user_a',
age: 50,
Expand Down Expand Up @@ -203,14 +205,16 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should delete record', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const snapshot = { id: 'user_a' };
const modelClass = store.modelFor('user');
const snapshot = store
.createRecord<UserModel>('user', { id: 'user_a' })
._createSnapshot() as Snapshot;
const adapter = this.owner.lookup(
'adapter:cloud-firestore-modular',
) as CloudFirestoreModularAdapter;

// Act
await adapter.deleteRecord(store, modelClass, snapshot as any);
await adapter.deleteRecord(store, modelClass, snapshot);

// Assert
const userA = await getDoc(doc(db, 'users/user_a'));
Expand All @@ -221,7 +225,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should delete record in a custom collection', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'post' } as ModelSchema;
const modelClass = store.modelFor('post');
const snapshot = {
id: 'post_b',

Expand All @@ -247,7 +251,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should delete record and process additional batched writes', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const snapshot = {
id: 'user_a',
adapterOptions: {
Expand Down Expand Up @@ -282,7 +286,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
const store = this.owner.lookup('service:store');
store.normalize = sinon.stub();
(store.push as (data: EmptyResourceDocument) => null) = sinon.stub();
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const adapter = this.owner.lookup(
'adapter:cloud-firestore-modular',
) as CloudFirestoreModularAdapter;
Expand Down Expand Up @@ -320,9 +324,11 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
const store = this.owner.lookup('service:store');
store.normalize = sinon.stub();
(store.push as (data: EmptyResourceDocument) => null) = sinon.stub();
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const modelId = 'user_a';
const snapshot = {};
const snapshot = store
.createRecord<UserModel>('user', {})
._createSnapshot() as Snapshot;
const adapter = this.owner.lookup(
'adapter:cloud-firestore-modular',
) as CloudFirestoreModularAdapter;
Expand All @@ -332,7 +338,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
store,
modelClass,
modelId,
snapshot as any,
snapshot,
);

// Assert
Expand All @@ -349,7 +355,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
const store = this.owner.lookup('service:store');
store.normalize = sinon.stub();
(store.push as (data: EmptyResourceDocument) => null) = sinon.stub();
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const modelId = 'user_a';
const snapshot = {
adapterOptions: {
Expand Down Expand Up @@ -381,16 +387,18 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
const store = this.owner.lookup('service:store');
store.normalize = sinon.stub();
(store.push as (data: EmptyResourceDocument) => null) = sinon.stub();
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const modelId = 'user_100';
const snapshot = {};
const snapshot = store
.createRecord<UserModel>('user', {})
._createSnapshot() as Snapshot;
const adapter = this.owner.lookup(
'adapter:cloud-firestore-modular',
) as CloudFirestoreModularAdapter;

try {
// Act
await adapter.findRecord(store, modelClass, modelId, snapshot as any);
await adapter.findRecord(store, modelClass, modelId, snapshot);
} catch (error) {
// Assert
assert.ok(error instanceof AdapterRecordNotFoundError);
Expand All @@ -408,7 +416,9 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
const store = this.owner.lookup('service:store');
store.normalize = sinon.stub();
(store.push as (data: EmptyResourceDocument) => null) = sinon.stub();
const snapshot = {};
const snapshot = store
.createRecord<UserModel>('user', {})
._createSnapshot() as Snapshot;
const url = 'users/user_a';
const relationship = { type: 'user', options: {} };
const adapter = this.owner.lookup(
Expand All @@ -418,7 +428,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
// Act
const result = await adapter.findBelongsTo(
store,
snapshot as any,
snapshot,
url,
relationship as any,
);
Expand Down Expand Up @@ -648,7 +658,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should query for records', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const queryRef = {
filter(reference: CollectionReference) {
return query(reference, where('age', '>=', 15), limit(1));
Expand Down Expand Up @@ -680,7 +690,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) {
test('should query for records in a custom collection', async function (assert) {
// Arrange
const store = this.owner.lookup('service:store');
const modelClass = { modelName: 'user' } as ModelSchema;
const modelClass = store.modelFor('user');
const queryRef = {
buildReference(firestore: Firestore) {
return collection(firestore, 'admins');
Expand Down

0 comments on commit d26033f

Please sign in to comment.