readonly base
Base
The simulated Base associated with this instance.
readonly cursor
Cursor
The Cursor instance associated with this instance's Base.
readonly globalConfig
GlobalConfig
A simulated GlobalConfig instance. This always starts empty.
readonly session
Session
A Session instance. This will correspond to the first
collaborator in your fixture data.
Container
function ( __namedParameters : Object ) => Element
A React Component which may be used to wrap Extension Components, enabling
them to run outside of a production Extensions environment.
import TestDriver from '@airtable/blocks-testing' ;
const MyCustomExtension = require ( '../src/my_custom_extension' ) ;
const myFixtureData = require ( './my_fixture_data' ) ;
const testDriver = new TestDriver ( myFixtureData ) ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
deleteFieldAsync
function ( tableIdOrName : TableId | string , fieldIdOrName : FieldId | string ) => Promise < void >
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
const testDriver = new TestDriver ( myFixtureData ) ;
let items , itemTexts ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
items = screen . getAllByRole ( 'listitem' ) ;
itemTexts = items . map ( ( el ) => el . textContent ) ;
expect ( itemTexts ) . toEqual ( [ '1st field' , '2nd field' , '3rd field' ] ) ;
await testDriver . deleteFieldAsync ( 'Table One' , '2nd field' ) ;
items = screen . getAllByRole ( 'listitem' ) ;
itemTexts = items . map ( ( el ) => el . textContent ) ;
expect ( itemTexts ) . toEqual ( [ '1st field' , '3rd field' ] ) ;
deleteTable
function ( tableIdOrName : TableId | string ) => void
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
const testDriver = new TestDriver ( myFixtureData ) ;
let items , itemTexts ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
items = screen . getAllByRole ( 'listitem' ) ;
itemTexts = items . map ( ( el ) => el . textContent ) ;
expect ( itemTexts ) . toEqual ( [ '1st table' , '2nd table' , '3rd table' ] ) ;
testDriver . deleteTable ( '2nd table' ) ;
items = screen . getAllByRole ( 'listitem' ) ;
itemTexts = items . map ( ( el ) => el . textContent ) ;
expect ( itemTexts ) . toEqual ( [ '1st table' , '3rd table' ] ) ;
deleteViewAsync
function ( tableIdOrName : TableId | string , viewIdOrName : ViewId | string ) => Promise < void >
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
const testDriver = new TestDriver ( myFixtureData ) ;
let items , itemTexts ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
items = screen . getAllByRole ( 'listitem' ) ;
itemTexts = items . map ( ( el ) => el . textContent ) ;
expect ( itemTexts ) . toEqual ( [ '1st view' , '2nd view' , '3rd view' ] ) ;
await testDriver . deleteViewAsync ( 'Table One' , '2nd view' ) ;
items = screen . getAllByRole ( 'listitem' ) ;
itemTexts = items . map ( ( el ) => el . textContent ) ;
expect ( itemTexts ) . toEqual ( [ '1st view' , '3rd view' ] ) ;
setActiveCursorModels
Update the active Table and/or the active View of the
Extension's Cursor . Either table
or view
must be specified.
testDriver . setActiveCursorModels ( { view : 'My grid view' } ) ;
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
const testDriver = new TestDriver ( myFixtureData ) ;
let heading ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
heading = screen . getByRole ( 'heading' ) ;
expect ( heading . textContent ) . toBe ( 'First table' ) ;
testDriver . setActiveCursorModels ( ( { table : 'Second table' } ) ;
heading = screen . getByRole ( 'heading' ) ;
expect ( heading . textContent ) . toBe ( 'Second table' ) ;
simulateExpandedRecordSelection
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
const testDriver = new TestDriver ( myFixtureData ) ;
testDriver . simulateExpandedRecordSelection ( ( tableId , recordIds ) => {
return recordIds [ 1 ] ;
} ) ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
const button = screen . getByRole ( 'button' , { name : 'Choose record' } ) ;
userEvent . click ( button ) ;
const heading = await waitFor ( ( ) => screen . getByRole ( 'heading' ) ) ;
expect ( heading . textContent )
. toBe ( 'You selected the record named "Number Two"' ) ;
simulatePermissionCheck
function ( check : function ( mutation : Mutation ) => boolean
) => void
Specify the outcome of internal permission checks. This influences the
behavior of not only explicit permission checks from Extensions code but also
the outcome of model operations such as createRecordsAsync .
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
const testDriver = new TestDriver ( myFixtureData ) ;
testDriver . simulatePermissionCheck ( ( mutation ) => {
return mutation . type !== 'createMultipleRecords' ;
} ) ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
const button = screen . getByRole ( 'button' , { name : 'Add' } ) ;
expect ( button . disabled ) . toBe ( true ) ;
unwatch
function ( key : Key , fn : function ( data : WatchableKeysAndArgs[Key] ) => void
) => void
import TestDriver from '@airtable/blocks-testing' ;
const MyCustomExtension = require ( '../src/my_custom_extension' ) ;
const myFixtureData = require ( './my_fixture_data' ) ;
let testDriver ;
let enterCount ;
let increment = ( ) => {
enterCount += 1 ;
} ) ;
beforeEach ( ( ) => {
testDriver = new TestDriver ( myFixtureData ) ;
enterCount = 0 ;
testDriver . watch ( 'enterFullscreen' , increment ) ;
} ) ;
afterEach ( ( ) => {
testDriver . unwatch ( 'enterFullscreen' , increment ) ;
} ) ;
userSelectRecords
function ( recordIds : Array < RecordId > ) => void
Simulate a user visually selecting a set of Records in
the active Table . This operation is unrelated to an Extension's
programmatic "selection" of records via, e.g. Table.selectRecords. To deselect all records, invoke this method with
an empty array.
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
const testDriver = new TestDriver ( myFixtureData ) ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
const records = await testDriver . base . tables [ 0 ] . selectRecordsAsync ( ) ;
testDriver . userSelectRecords ( [ records [ 1 ] . id , records [ 3 ] . id ] ) ;
const heading = await waitFor ( ( ) => screen . getByRole ( 'heading' ) ) ;
expect ( heading . textContent ) . toBe ( '2 records selected' ) ;
watch
function ( key : Key , fn : function ( data : WatchableKeysAndArgs[Key] ) => void
) => void
Register a function to be invoked in response to a given internal event.
See WatchableKeysAndArgs for the available keys and the values
which are included when they are emitted.
import TestDriver from '@airtable/blocks-testing' ;
import MyCustomExtension from '../src/my_custom_extension' ;
import myFixtureData from './my_fixture_data' ;
import { render , screen } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
const testDriver = new TestDriver ( myFixtureData ) ;
let expandedRecordIds = [ ] ;
testDriver . watch ( 'expandRecord' , ( { recordId } ) => {
expendedRecordIds . push ( recordId ) ;
} ) ;
render (
< testDriver.Container >
< MyCustomExtension />
</ testDriver.Container >
) ;
expect ( expandedRecords ) . toEqual ( [ ] ) ;
const buttons = screen . getAllByRole ( 'button' ) ;
userEvent . click ( buttons [ 1 ] ) ;
expect ( expandedRecords ) . toEqual ( [ 'rec2' ] ) ;