Skip to content

Commit 7ee6662

Browse files
committed
feat: test airtable uploads
1 parent 605ce2e commit 7ee6662

3 files changed

Lines changed: 128 additions & 56 deletions

File tree

forms-bridge/addons/airtable/class-airtable-form-bridge.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,10 @@ function ( $name ) use ( $attachment_name ) {
296296
)->post(
297297
"/v0/{$base_id}/{$record_id}/{$attachment['id']}/uploadAttachment",
298298
array(
299-
'contentType' => $filetype['type'],
299+
'contentType' => $filetype['type'] ?? 'octet/stream',
300300
'file' => $attachment['file'],
301301
'filename' => $filename,
302-
)
302+
),
303303
);
304304

305305
if ( is_wp_error( $upload_response ) ) {

tests/addons/test-airtable.php

Lines changed: 125 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ private static function get_mock_response( $method, $path, $body ) {
184184
),
185185
),
186186
);
187-
} elseif ( preg_match( '#/v0/meta/bases/(app\d+)/tables#', $path, $matches ) ) {
187+
} elseif ( preg_match( '#^/v0/meta/bases/(app\d+)/tables$#', $path, $matches ) ) {
188188
// Tables for a specific base.
189189
return array(
190190
'tables' => array(
@@ -213,15 +213,36 @@ private static function get_mock_response( $method, $path, $body ) {
213213
'type' => 'number',
214214
),
215215
array(
216-
'id' => 'fld888888888',
217-
'name' => 'Tags',
218-
'type' => 'multipleSelects',
216+
'id' => 'fld888888888',
217+
'name' => 'Tags',
218+
'type' => 'multipleSelects',
219+
'options' => array(
220+
'choices' => array(
221+
array(
222+
'name' => 'A',
223+
'id' => 't1',
224+
),
225+
array(
226+
'name' => 'B',
227+
'id' => 't2',
228+
),
229+
array(
230+
'name' => 'C',
231+
'id' => 't3',
232+
),
233+
),
234+
),
219235
),
220236
array(
221237
'id' => 'fld999999999',
222238
'name' => 'Summary',
223239
'type' => 'aiText',
224240
),
241+
array(
242+
'id' => 'fld2222222222',
243+
'name' => 'Profile Picture',
244+
'type' => 'multipleAttachments',
245+
),
225246
),
226247
),
227248
array(
@@ -239,45 +260,73 @@ private static function get_mock_response( $method, $path, $body ) {
239260
),
240261
);
241262
}
242-
} elseif ( preg_match( '#/v0/(app\d+)/([^/]+)#', $path, $matches ) ) {
263+
} elseif ( preg_match( '#^/v0/(app\d+)/([^/]+)$#', $path, $matches ) ) {
243264
// Table data endpoint.
244265
if ( 'GET' === $method ) {
245266
// Mock field schema for GET requests.
246267
return array(
247-
'fields' => array(
268+
'records' => array(
248269
array(
249-
'id' => 'fld123456789',
250-
'name' => 'Name',
251-
'type' => 'singleLineText',
252-
),
253-
array(
254-
'id' => 'fld987654321',
255-
'name' => 'Email',
256-
'type' => 'email',
257-
),
258-
array(
259-
'id' => 'fld555555555',
260-
'name' => 'Active',
261-
'type' => 'checkbox',
262-
),
263-
array(
264-
'id' => 'fld777777777',
265-
'name' => 'Score',
266-
'type' => 'number',
267-
),
268-
array(
269-
'id' => 'fld888888888',
270-
'name' => 'Tags',
271-
'type' => 'multipleSelects',
270+
'id' => 'rec123456789',
271+
'createdTime' => '2023-01-01T00:00:00.000Z',
272+
'fields' => array(
273+
array(
274+
'id' => 'fld123456789',
275+
'name' => 'Name',
276+
'type' => 'singleLineText',
277+
),
278+
array(
279+
'id' => 'fld987654321',
280+
'name' => 'Email',
281+
'type' => 'email',
282+
),
283+
array(
284+
'id' => 'fld555555555',
285+
'name' => 'Active',
286+
'type' => 'checkbox',
287+
),
288+
array(
289+
'id' => 'fld777777777',
290+
'name' => 'Score',
291+
'type' => 'number',
292+
),
293+
array(
294+
'id' => 'fld888888888',
295+
'name' => 'Tags',
296+
'type' => 'multipleSelects',
297+
),
298+
),
272299
),
273300
),
274301
);
275302
} elseif ( 'POST' === $method ) {
276303
// Mock successful record creation for POST requests.
277304
return array(
278-
'id' => 'rec123456789',
279-
'fields' => $body['records'][0]['fields'],
280-
'createdTime' => '2023-01-01T00:00:00.000Z',
305+
'records' => array(
306+
array(
307+
'id' => 'rec123456789',
308+
'fields' => $body['records'][0]['fields'],
309+
'createdTime' => '2023-01-01T00:00:00.000Z',
310+
),
311+
),
312+
);
313+
}
314+
} elseif ( preg_match( '#^/v0/(app\d+)/([^/]+)/uploadAttachment$#', $path, $matches ) ) {
315+
if ( $method === 'POST' ) {
316+
return array(
317+
'createdTime' => '2022-02-01T21:25:05.663Z',
318+
'fields' => array(
319+
'fld00000000000000' => array(
320+
array(
321+
'filename' => 'sample.txt',
322+
'id' => 'att00000000000000',
323+
'size' => 11,
324+
'type' => 'text/plain',
325+
'url' => 'https://v5.airtableusercontent.com/v3/u/29/29/1716940800000/ffhiecnieIwxisnIBDSAln/foDeknw_G5CdkdPW1j-U0yUCX9YSaE1EJft3wvXb85pnTY1sKZdYeFvKpsM-fqOa6Bnu5MQVPA_ApINEUXL_E3SAZn6z01VN9Pn9SluhSy4NoakZGapcvl4tuN3jktO2Dt7Ck_gh4oMdsrcV8J-t_A/53m17XmDDHsNtIqzM1PQVnRKutK6damFgNNS5WCaTbI',
326+
),
327+
),
328+
),
329+
'id' => 'rec00000000000000',
281330
);
282331
}
283332
}
@@ -372,16 +421,49 @@ public function test_post_create_record() {
372421
);
373422

374423
$payload = array(
375-
'Name' => 'John Doe',
376-
'Email' => 'john.doe@example.com',
424+
'Name' => 'John Doe',
425+
'Email' => 'john.doe@example.com',
426+
'Score' => 99,
427+
'Tags' => array( 'A', 'B' ),
428+
'Active' => true,
377429
);
378430

379431
$response = $bridge->submit( $payload );
380432

381433
$this->assertFalse( is_wp_error( $response ) );
382434
$this->assertArrayHasKey( 'data', $response );
383-
$this->assertEquals( 'rec123456789', $response['data']['id'] );
384-
$this->assertEquals( 'John Doe', $response['data']['fields']['Name'] );
435+
$this->assertEquals( 'rec123456789', $response['data']['records'][0]['id'] );
436+
$this->assertEquals( 'John Doe', $response['data']['records'][0]['fields']['Name'] );
437+
}
438+
439+
/**
440+
* Test POST request to create a record with uploads.
441+
*/
442+
public function test_post_create_record_with_uploads() {
443+
$bridge = new Airtable_Form_Bridge(
444+
array(
445+
'name' => self::BRIDGE_NAME,
446+
'backend' => self::BACKEND_NAME,
447+
'endpoint' => '/v0/app123456789/Contacts',
448+
'method' => 'POST',
449+
)
450+
);
451+
452+
$payload = array(
453+
'Name' => 'John Doe',
454+
'Email' => 'john.doe@example.com',
455+
'Score' => 99,
456+
'Tags' => array( 'A', 'B' ),
457+
'Active' => true,
458+
'Profile Picture' => 'file',
459+
);
460+
461+
$response = $bridge->submit( $payload );
462+
463+
$this->assertFalse( is_wp_error( $response ) );
464+
$this->assertArrayHasKey( 'data', $response );
465+
$this->assertEquals( 'rec123456789', $response['data']['records'][0]['id'] );
466+
$this->assertEquals( 'John Doe', $response['data']['records'][0]['fields']['Name'] );
385467
}
386468

387469
/**
@@ -401,8 +483,10 @@ public function test_get_table_schema() {
401483

402484
$this->assertFalse( is_wp_error( $response ) );
403485
$this->assertArrayHasKey( 'data', $response );
404-
$this->assertArrayHasKey( 'fields', $response['data'] );
405-
$this->assertCount( 5, $response['data']['fields'] );
486+
$this->assertArrayHasKey( 'records', $response['data'] );
487+
$this->assertCount( 1, $response['data']['records'] );
488+
$this->assertArrayHasKey( 'fields', $response['data']['records'][0] );
489+
$this->assertCount( 5, $response['data']['records'][0]['fields'] );
406490
}
407491

408492
/**
@@ -474,6 +558,7 @@ public function test_addon_get_endpoint_schema_post() {
474558
$this->assertContains( 'Active', $field_names );
475559
$this->assertContains( 'Score', $field_names );
476560
$this->assertContains( 'Tags', $field_names );
561+
$this->assertContains( 'Profile Picture', $field_names );
477562

478563
// Check field types.
479564
$schema_map = array();
@@ -486,6 +571,7 @@ public function test_addon_get_endpoint_schema_post() {
486571
$this->assertEquals( 'boolean', $schema_map['Active'] );
487572
$this->assertEquals( 'number', $schema_map['Score'] );
488573
$this->assertEquals( 'array', $schema_map['Tags'] );
574+
$this->assertEquals( 'file', $schema_map['Profile Picture'] );
489575
}
490576

491577
/**
@@ -581,20 +667,6 @@ public function test_authorization_header_transformation() {
581667
* Test field filtering in schema - should exclude certain field types.
582668
*/
583669
public function test_field_filtering_in_schema() {
584-
// Add a field that should be excluded.
585-
$mock_fields = array(
586-
array(
587-
'id' => 'fld_excluded',
588-
'name' => 'ExcludedField',
589-
'type' => 'aiText', // This type should be excluded.
590-
),
591-
array(
592-
'id' => 'fld_included',
593-
'name' => 'IncludedField',
594-
'type' => 'singleLineText', // This type should be included.
595-
),
596-
);
597-
598670
$addon = Addon::addon( 'airtable' );
599671
$schema = $addon->get_endpoint_schema(
600672
'/v0/app123456789/Contacts',
@@ -606,6 +678,6 @@ public function test_field_filtering_in_schema() {
606678
$field_names = array_column( $schema, 'name' );
607679
$this->assertContains( 'Name', $field_names );
608680
$this->assertNotContains( 'Summary', $field_names );
609-
$this->assertCount( 5, $schema );
681+
$this->assertCount( 6, $schema );
610682
}
611683
}

tests/addons/test-grist.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ public function test_post_create_record() {
446446
}
447447

448448
/**
449-
* Test POST request to create a record.
449+
* Test POST request to create a record with uploads.
450450
*/
451451
public function test_post_create_record_with_upload() {
452452
$bridge = new Grist_Form_Bridge(

0 commit comments

Comments
 (0)