Skip to content

Commit

Permalink
test(base): tweak tests after validation schedule optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
bjoerge committed Sep 26, 2022
1 parent 581df88 commit 0e90d2c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {combineLatest, Observable} from 'rxjs'
import {map, publishReplay, refCount, startWith, switchMap} from 'rxjs/operators'
import {SanityClient} from '@sanity/client'
import {IdPair, PendingMutationsEvent} from '../types'
import {HistoryStore} from '../../history'
import {isLiveEditEnabled} from './utils/isLiveEditEnabled'
import {snapshotPair} from './snapshotPair'

Expand All @@ -26,7 +25,6 @@ const NOT_LOCKED: TransactionSyncLockState = {enabled: false}
export const editState = (
ctx: {
client: SanityClient
historyStore: HistoryStore
schema: Schema
},
idPair: IdPair,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {SanityClient} from '@sanity/client'
import {concat, ConnectableObservable, timer, Observable, Subject, of} from 'rxjs'
import {buffer, takeWhile, first, publish, mapTo} from 'rxjs/operators'
import {DocumentPreviewStore} from '../../../preview'
import {concat, ConnectableObservable, defer, EMPTY, Observable, of, Subject, timer} from 'rxjs'
import {buffer, first, publish, takeWhile} from 'rxjs/operators'
import {DocumentAvailability, DraftsModelDocumentAvailability} from '../../../preview'
import {createSchema} from '../../../schema'
import {createMockSanityClient} from '../../../../test/mocks/mockSanityClient'
import {editState, EditStateFor} from './editState'
Expand All @@ -27,12 +27,21 @@ const schema = createSchema({
],
})

const AVAILABLE: DocumentAvailability = {available: true, reason: 'READABLE'}
const NOT_FOUND: DocumentAvailability = {available: false, reason: 'NOT_FOUND'}

// A fixture used to set up a validation stream/subscription and wait
// for certain events (e.g. when validation is finished running)
function createSubscription(client: SanityClient, documentPreviewStore?: DocumentPreviewStore) {
function createSubscription(
client: SanityClient,
observeDocumentPairAvailability: (
id: string
) => Observable<DraftsModelDocumentAvailability> = jest.fn().mockReturnValue(EMPTY)
) {
const getClient = () => client

const stream = validation(
{client, getClient, documentPreviewStore, schema} as any,
{client, getClient, schema, observeDocumentPairAvailability},
{publishedId: 'example-id', draftId: 'drafts.example-id'},
'movie'
).pipe(publish())
Expand All @@ -54,27 +63,35 @@ function createSubscription(client: SanityClient, documentPreviewStore?: Documen
},
}
}
// @todo: fix mock sanity client is not compatible with SanityClient
function getMockClient() {
return createMockSanityClient() as any as SanityClient
}

/**
* READ THIS: Each tests passes when being run individually, but not when run as part of the whole suite.
* It's probably a symptom of something wrong with the caching and should be investigated.
*/
describe('validation', () => {
beforeEach(() => {
mockEditState.mockReset()
})

it('runs `editState` through `validateDocument` to create a stream of validation statuses', async () => {
const client = createMockSanityClient()
const client = getMockClient()
const mockEditStateSubject = new Subject<EditStateFor>()

mockEditState.mockImplementation(() => mockEditStateSubject.asObservable())

const {subscription, closeSubscription, doneValidating} = createSubscription(client as any)
const {subscription, closeSubscription, doneValidating} = createSubscription(client)

// simulate first emission from validation listener
mockEditStateSubject.next({
id: 'example-id',
draft: {
_id: 'example-id',
_createdAt: '2021-09-07T16:23:52.256Z',
_rev: 'exampleRev',
_rev: 'exampleRev1',
_type: 'movie',
_updatedAt: '2021-09-07T16:23:52.256Z',
title: 5,
Expand Down Expand Up @@ -105,23 +122,24 @@ describe('validation', () => {
],
},
])
mockEditStateSubject.complete()
})

it.skip('re-runs validation when the edit state changes', async () => {
const client = createMockSanityClient()
const client = getMockClient()
const mockEditStateSubject = new Subject<EditStateFor>()

mockEditState.mockImplementation(() => mockEditStateSubject.asObservable())

const {subscription, closeSubscription, doneValidating} = createSubscription(client as any)
const {subscription, closeSubscription, doneValidating} = createSubscription(client)

// simulate first emission from validation listener
mockEditStateSubject.next({
id: 'example-id',
draft: {
_id: 'example-id',
_createdAt: '2021-09-07T16:23:52.256Z',
_rev: 'exampleRev',
_rev: 'exampleRev2',
_type: 'movie',
_updatedAt: '2021-09-07T16:23:52.256Z',
title: 5,
Expand All @@ -142,7 +160,7 @@ describe('validation', () => {
draft: {
_id: 'example-id',
_createdAt: '2021-09-07T16:23:52.256Z',
_rev: 'exampleRev',
_rev: 'exampleRev3',
_type: 'movie',
_updatedAt: '2021-09-07T16:23:52.256Z',
title: 'valid title',
Expand All @@ -167,35 +185,39 @@ describe('validation', () => {
{isValidating: true, validation: [{item: {message: 'Expected type "String", got "Number"'}}]},
{isValidating: false, validation: []},
])
mockEditStateSubject.complete()
})

it.skip('re-runs validation when dependency events change', async () => {
const client = createMockSanityClient()
const subject = new Subject()
const mockPreviewStore: any = {}
const client = getMockClient()
const subject = new Subject<DraftsModelDocumentAvailability>()

// Mock `editState`
const mockEditStateSubject = new Subject<EditStateFor>()
mockEditState.mockImplementation(() => mockEditStateSubject.asObservable())

const observeDocumentPairAvailability = (
id: string
): Observable<DraftsModelDocumentAvailability> =>
id === 'example-ref-id'
? concat(of({published: AVAILABLE, draft: AVAILABLE}), subject)
: concat(
of({published: AVAILABLE, draft: AVAILABLE}),
of({published: AVAILABLE, draft: AVAILABLE})
)

const {subscription, closeSubscription, doneValidating} = createSubscription(
client as any,
mockPreviewStore
client,
observeDocumentPairAvailability
)

mockPreviewStore.unstable_observeDocumentPairAvailability = () =>
concat(
of({published: {available: true}}),
subject.pipe(mapTo({published: {available: false}}))
)

// simulate first emission from validation listener
mockEditStateSubject.next({
id: 'example-id',
draft: {
_id: 'example-id',
_createdAt: '2021-09-07T16:23:52.256Z',
_rev: 'exampleRev',
_rev: 'exampleRev4',
_type: 'movie',
_updatedAt: '2021-09-07T16:23:52.256Z',
title: 'testing',
Expand All @@ -210,22 +232,17 @@ describe('validation', () => {
})
await doneValidating()

mockPreviewStore.unstable_observeDocumentPairAvailability = (id: string) =>
id === 'example-ref-id'
? of({published: {available: false}})
: of({published: {available: true}})

subject.next()
subject.next({published: NOT_FOUND, draft: AVAILABLE})

await doneValidating()

// close the buffer
closeSubscription()

await expect(subscription).resolves.toMatchObject([
{isValidating: true, validation: []},
{isValidating: false, validation: []},
{isValidating: true, validation: []},
expect(await subscription).toMatchObject([
{isValidating: true, validation: [], revision: 'exampleRev4'},
{isValidating: false, validation: [], revision: 'exampleRev4'},
{isValidating: true, validation: [], revision: 'exampleRev4'},
{
isValidating: false,
validation: [
Expand All @@ -237,19 +254,26 @@ describe('validation', () => {
],
},
])
mockEditStateSubject.complete()
})

// this means that when you subscribe to the same document, you'll
// immediately get the previous value emitted to you
// @todo: investigate why this fails
it.skip('replays the last known version via `memoize` and `publishReplay`', async () => {
const client = createMockSanityClient()
const client = getMockClient()

// Mock `editState`
const mockEditStateSubject = new Subject<EditStateFor>()
mockEditState.mockImplementation(() => mockEditStateSubject.asObservable())

const subscription = validation(
{client, schema} as any,
{
client,
schema,
getClient: () => client,
observeDocumentPairAvailability: jest.fn().mockReturnValue(EMPTY),
},
{publishedId: 'example-id', draftId: 'drafts.example-id'},
'movie'
)
Expand All @@ -262,7 +286,7 @@ describe('validation', () => {
draft: {
_id: 'example-id',
_createdAt: '2021-09-07T16:23:52.256Z',
_rev: 'exampleRev',
_rev: 'exampleRev5',
_type: 'movie',
_updatedAt: '2021-09-07T16:23:52.256Z',
title: 5,
Expand Down Expand Up @@ -314,13 +338,13 @@ describe('validation', () => {
})

it.skip('returns empty validation message arrays if there is no available published or draft snapshot', async () => {
const client = createMockSanityClient()
const client = getMockClient()

// Mock `editState`
const mockEditStateSubject = new Subject<EditStateFor>()
mockEditState.mockImplementation(() => mockEditStateSubject.asObservable())

const {subscription, closeSubscription, doneValidating} = createSubscription(client as any)
const {subscription, closeSubscription, doneValidating} = createSubscription(client)

mockEditStateSubject.next({
id: 'example-id',
Expand All @@ -335,9 +359,6 @@ describe('validation', () => {
await doneValidating()
closeSubscription()

await expect(subscription).resolves.toMatchObject([
{isValidating: true, validation: []},
{isValidating: false, validation: []},
])
await expect(subscription).resolves.toMatchObject([{isValidating: false, validation: []}])
})
})

0 comments on commit 0e90d2c

Please sign in to comment.