Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3373,7 +3373,7 @@ describe('EditorComponent', () => {
env.dispose();
}));

it('should remove resolved notes after a remote update', fakeAsync(() => {
it('should remove resolved notes after a remote update', fakeAsync(async () => {
const env = new TestEnvironment();
env.setProjectUserConfig();
env.wait();
Expand All @@ -3382,7 +3382,7 @@ describe('EditorComponent', () => {
let noteThreadEmbedCount = env.countNoteThreadEmbeds(contents.ops!);
expect(noteThreadEmbedCount).toEqual(5);

env.resolveNote('project01', 'dataid01');
await env.resolveNote('project01', 'dataid01');
contents = env.targetEditor.getContents();
noteThreadEmbedCount = env.countNoteThreadEmbeds(contents.ops!);
expect(noteThreadEmbedCount).toEqual(4);
Expand Down Expand Up @@ -5594,10 +5594,9 @@ class TestEnvironment {
return noteEmbedCount;
}

resolveNote(projectId: string, threadId: string): void {
async resolveNote(projectId: string, threadId: string): Promise<void> {
const noteDoc: NoteThreadDoc = this.getNoteThreadDoc(projectId, threadId);
noteDoc.submitJson0Op(op => op.set(n => n.status, NoteStatus.Resolved));
this.realtimeService.updateQueryAdaptersRemote();
await this.realtimeService.simulateRemoteChangeJson0Op(noteDoc, op => op.set(n => n.status, NoteStatus.Resolved));
this.wait();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export class MemoryRealtimeRemoteStore extends RealtimeRemoteStore {
// getAccessToken is not used in this memory implementation
}

/** Write a realtime doc into the store, for a given collection. An existing realtime doc with the same id is
* overwritten. */
addSnapshot<T>(collection: string, snapshot: Snapshot<T>): void {
let collectionSnapshots = this.snapshots.get(collection);
if (collectionSnapshots == null) {
Expand Down Expand Up @@ -132,7 +134,7 @@ export class MemoryRealtimeDocAdapter implements RealtimeDocAdapter {
return Promise.resolve();
}

submitOp(op: any, source?: any): Promise<void> {
submitOpWithoutEmitting(op: any): void {
if (this.type == null) {
throw new Error('The doc has not been loaded.');
}
Expand All @@ -143,6 +145,11 @@ export class MemoryRealtimeDocAdapter implements RealtimeDocAdapter {
}
this.data = this.type.apply(this.data, op);
this.version++;
}

/** Multiple operations are received for the `op` argument. */
submitOp(op: any, source?: any): Promise<void> {
this.submitOpWithoutEmitting(op);
this.emitChange(op);
if (!source) {
this.emitRemoteChange(op);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { Injectable } from '@angular/core';
import { merge } from 'lodash-es';
import * as OTJson0 from 'ot-json0';
import { Json0OpBuilder } from 'realtime-server/lib/esm/common/utils/json0-op-builder';
import { MemoryOfflineStore } from './memory-offline-store';
import { MemoryRealtimeQueryAdapter, MemoryRealtimeRemoteStore } from './memory-realtime-remote-store';
import {
MemoryRealtimeDocAdapter,
MemoryRealtimeQueryAdapter,
MemoryRealtimeRemoteStore
} from './memory-realtime-remote-store';
import { FileOfflineData, FileType } from './models/file-offline-data';
import { RealtimeDoc } from './models/realtime-doc';
import { Snapshot } from './models/snapshot';
import { RealtimeService } from './realtime.service';
import { objectId } from './utils';
Expand Down Expand Up @@ -33,6 +39,8 @@ export class TestRealtimeService extends RealtimeService {
}
}

/** Write a realtime doc into the store, for a given collection. An existing realtime doc with the same id is
* overwritten. */
addSnapshot<T>(collection: string, snapshot: Partial<Snapshot<T>>, addToOfflineStore: boolean = false): void {
const completeSnapshot = addSnapshotDefaults(snapshot);
(this.remoteStore as MemoryRealtimeRemoteStore).addSnapshot(collection, completeSnapshot);
Expand All @@ -57,6 +65,48 @@ export class TestRealtimeService extends RealtimeService {
}
}

/** Intended to do the same thing as `updateQueryAdaptersRemote` but without remoteChanges$ emitting, which can be
* done in follow up. */
updateQueryAdaptersRemoteQuietly(): MemoryRealtimeQueryAdapter[] {
const adaptersToEmit: MemoryRealtimeQueryAdapter[] = [];
for (const collectionQueries of this.subscribeQueries.values()) {
for (const query of collectionQueries) {
const adapter = query.adapter as MemoryRealtimeQueryAdapter;
if ((adapter as any).performQuery()) {
adaptersToEmit.push(adapter);
}
}
}
return adaptersToEmit;
}

/** Simulate a change happening externally. The MemoryRealtimeDocAdapter data and MemoryRealtimeQueryAdapter results
* are updated before changes are announced, so when changes begin to be announced, the docs and queries are all
* up-to-date. The order of emits, and presence or absence of RealtimeQuery.remoteDocChanges$, may be different than
* when running the app. */
async simulateRemoteChange(doc: RealtimeDoc, ops: any): Promise<void> {
const docAdapter: MemoryRealtimeDocAdapter = doc.adapter as MemoryRealtimeDocAdapter;
// Submitting ops to the realtime doc adapter to simulate writing data on a remote server may seem backwards but
// is getting the job done.
docAdapter.submitOpWithoutEmitting(ops);
const queryAdaptersToEmit: MemoryRealtimeQueryAdapter[] = this.updateQueryAdaptersRemoteQuietly();
docAdapter.emitChange(ops);
docAdapter.emitRemoteChange(ops);
for (const adapter of queryAdaptersToEmit) {
adapter.remoteChanges$.next();
}
}

async simulateRemoteChangeJson0Op<T>(
doc: RealtimeDoc<T>,
build: (builder: Json0OpBuilder<T>) => void
): Promise<void> {
if (doc.data == null) throw new Error('Cannot simulate remote change on document with null data');
const builder = new Json0OpBuilder(doc.data) as Json0OpBuilder<T>;
build(builder);
if (builder.op.length > 0) await this.simulateRemoteChange(doc, builder.op);
}

async updateQueriesLocal(): Promise<void> {
for (const collectionQueries of this.subscribeQueries.values()) {
for (const query of collectionQueries) {
Expand Down
Loading