| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | package core_test | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 	"github.com/pocketbase/pocketbase/core" | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	"github.com/pocketbase/pocketbase/tests" | 
					
						
							|  |  |  | 	"github.com/pocketbase/pocketbase/tools/list" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestExpandRecords(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-01-03 10:30:20 +08:00
										 |  |  | 	t.Parallel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	app, _ := tests.NewTestApp() | 
					
						
							|  |  |  | 	defer app.Cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		testName                  string | 
					
						
							|  |  |  | 		collectionIdOrName        string | 
					
						
							|  |  |  | 		recordIds                 []string | 
					
						
							|  |  |  | 		expands                   []string | 
					
						
							|  |  |  | 		fetchFunc                 core.ExpandFetchFunc | 
					
						
							|  |  |  | 		expectNonemptyExpandProps int | 
					
						
							|  |  |  | 		expectExpandFailures      int | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"empty records", | 
					
						
							|  |  |  | 			"", | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			[]string{}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			[]string{"self_rel_one", "self_rel_many.self_rel_one"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"empty expand", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"i9naidtvr6qsgb4", "qzaqccwrmva4o1n"}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			[]string{}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"fetchFunc with error", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"i9naidtvr6qsgb4", "qzaqccwrmva4o1n"}, | 
					
						
							|  |  |  | 			[]string{"self_rel_one", "self_rel_many.self_rel_one"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 				return nil, errors.New("test error") | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			2, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"missing relation field", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"i9naidtvr6qsgb4", "qzaqccwrmva4o1n"}, | 
					
						
							|  |  |  | 			[]string{"missing"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			1, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-07-30 12:58:42 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"existing, but non-relation type field", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"i9naidtvr6qsgb4", "qzaqccwrmva4o1n"}, | 
					
						
							| 
									
										
										
										
											2022-07-30 12:58:42 +08:00
										 |  |  | 			[]string{"title"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-30 12:58:42 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			1, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"invalid/missing second level expand", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"i9naidtvr6qsgb4", "qzaqccwrmva4o1n"}, | 
					
						
							|  |  |  | 			[]string{"rel_one_no_cascade.title"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			1, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2023-07-14 13:36:01 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			"with nil fetchfunc", | 
					
						
							|  |  |  | 			"users", | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"bgs820n361vj1qd", | 
					
						
							|  |  |  | 				"4q1xlclmfloku33", | 
					
						
							|  |  |  | 				"oap640cot4yru2s", // no rels
 | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			[]string{"rel"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 			2, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"expand normalizations", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"i9naidtvr6qsgb4", "qzaqccwrmva4o1n"}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			[]string{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 				"self_rel_one", "self_rel_many.self_rel_many.rel_one_no_cascade", | 
					
						
							|  |  |  | 				"self_rel_many.self_rel_one.self_rel_many.self_rel_one.rel_one_no_cascade", | 
					
						
							|  |  |  | 				"self_rel_many", "self_rel_many.", | 
					
						
							|  |  |  | 				"  self_rel_many  ", "", | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			9, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-09-21 18:34:34 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"single expand", | 
					
						
							|  |  |  | 			"users", | 
					
						
							| 
									
										
										
										
											2022-09-21 18:34:34 +08:00
										 |  |  | 			[]string{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 				"bgs820n361vj1qd", | 
					
						
							|  |  |  | 				"4q1xlclmfloku33", | 
					
						
							|  |  |  | 				"oap640cot4yru2s", // no rels
 | 
					
						
							| 
									
										
										
										
											2022-09-21 18:34:34 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			[]string{"rel"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-09-21 18:34:34 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			2, | 
					
						
							| 
									
										
										
										
											2022-09-21 18:34:34 +08:00
										 |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2023-07-14 13:36:01 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			"with nil fetchfunc", | 
					
						
							|  |  |  | 			"users", | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"bgs820n361vj1qd", | 
					
						
							|  |  |  | 				"4q1xlclmfloku33", | 
					
						
							|  |  |  | 				"oap640cot4yru2s", // no rels
 | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			[]string{"rel"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 			2, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"maxExpandDepth reached", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"qzaqccwrmva4o1n"}, | 
					
						
							|  |  |  | 			[]string{"self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			6, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			"simple back single relation field expand (deprecated syntax)", | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"demo3", | 
					
						
							|  |  |  | 			[]string{"lcl9d87w22ml6jy"}, | 
					
						
							|  |  |  | 			[]string{"demo4(rel_one_no_cascade_required)"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			1, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			"simple back expand via single relation field", | 
					
						
							|  |  |  | 			"demo3", | 
					
						
							|  |  |  | 			[]string{"lcl9d87w22ml6jy"}, | 
					
						
							|  |  |  | 			[]string{"demo4_via_rel_one_no_cascade_required"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			1, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"nested back expand via single relation field", | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"demo3", | 
					
						
							|  |  |  | 			[]string{"lcl9d87w22ml6jy"}, | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 				"demo4_via_rel_one_no_cascade_required.self_rel_many.self_rel_many.self_rel_one", | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			5, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			"nested back expand via multiple relation field", | 
					
						
							|  |  |  | 			"demo3", | 
					
						
							|  |  |  | 			[]string{"lcl9d87w22ml6jy"}, | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"demo4_via_rel_many_no_cascade_required.self_rel_many.rel_many_no_cascade_required.demo4_via_rel_many_no_cascade_required", | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			7, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-12-20 17:07:16 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			"expand multiple relations sharing a common path", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			[]string{"qzaqccwrmva4o1n"}, | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"rel_one_no_cascade", | 
					
						
							|  |  |  | 				"rel_many_no_cascade", | 
					
						
							|  |  |  | 				"self_rel_many.self_rel_one.rel_many_cascade", | 
					
						
							|  |  |  | 				"self_rel_many.self_rel_one.rel_many_no_cascade_required", | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-12-20 17:07:16 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			5, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 	for _, s := range scenarios { | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		t.Run(s.testName, func(t *testing.T) { | 
					
						
							|  |  |  | 			ids := list.ToUniqueStringSlice(s.recordIds) | 
					
						
							|  |  |  | 			records, _ := app.FindRecordsByIds(s.collectionIdOrName, ids) | 
					
						
							|  |  |  | 			failed := app.ExpandRecords(records, s.expands, s.fetchFunc) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			if len(failed) != s.expectExpandFailures { | 
					
						
							|  |  |  | 				t.Errorf("Expected %d failures, got %d\n%v", s.expectExpandFailures, len(failed), failed) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			encoded, _ := json.Marshal(records) | 
					
						
							|  |  |  | 			encodedStr := string(encoded) | 
					
						
							|  |  |  | 			totalExpandProps := strings.Count(encodedStr, `"`+core.FieldNameExpand+`":`) | 
					
						
							|  |  |  | 			totalEmptyExpands := strings.Count(encodedStr, `"`+core.FieldNameExpand+`":{}`) | 
					
						
							|  |  |  | 			totalNonemptyExpands := totalExpandProps - totalEmptyExpands | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			if s.expectNonemptyExpandProps != totalNonemptyExpands { | 
					
						
							|  |  |  | 				t.Errorf("Expected %d expand props, got %d\n%v", s.expectNonemptyExpandProps, totalNonemptyExpands, encodedStr) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestExpandRecord(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-01-03 10:30:20 +08:00
										 |  |  | 	t.Parallel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	app, _ := tests.NewTestApp() | 
					
						
							|  |  |  | 	defer app.Cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		testName                  string | 
					
						
							|  |  |  | 		collectionIdOrName        string | 
					
						
							|  |  |  | 		recordId                  string | 
					
						
							|  |  |  | 		expands                   []string | 
					
						
							|  |  |  | 		fetchFunc                 core.ExpandFetchFunc | 
					
						
							|  |  |  | 		expectNonemptyExpandProps int | 
					
						
							|  |  |  | 		expectExpandFailures      int | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"empty expand", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"i9naidtvr6qsgb4", | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			[]string{}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"fetchFunc with error", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"i9naidtvr6qsgb4", | 
					
						
							|  |  |  | 			[]string{"self_rel_one", "self_rel_many.self_rel_one"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 				return nil, errors.New("test error") | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			2, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"missing relation field", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"i9naidtvr6qsgb4", | 
					
						
							|  |  |  | 			[]string{"missing"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			1, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"existing, but non-relation type field", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"i9naidtvr6qsgb4", | 
					
						
							|  |  |  | 			[]string{"title"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			1, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"invalid/missing second level expand", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"qzaqccwrmva4o1n", | 
					
						
							|  |  |  | 			[]string{"rel_one_no_cascade.title"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			1, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"expand normalizations", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"qzaqccwrmva4o1n", | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"self_rel_one", "self_rel_many.self_rel_many.rel_one_no_cascade", | 
					
						
							|  |  |  | 				"self_rel_many.self_rel_one.self_rel_many.self_rel_one.rel_one_no_cascade", | 
					
						
							|  |  |  | 				"self_rel_many", "self_rel_many.", | 
					
						
							|  |  |  | 				"  self_rel_many  ", "", | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			8, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"no rels to expand", | 
					
						
							|  |  |  | 			"users", | 
					
						
							|  |  |  | 			"oap640cot4yru2s", | 
					
						
							|  |  |  | 			[]string{"rel"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"maxExpandDepth reached", | 
					
						
							|  |  |  | 			"demo4", | 
					
						
							|  |  |  | 			"qzaqccwrmva4o1n", | 
					
						
							|  |  |  | 			[]string{"self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many.self_rel_many"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			6, | 
					
						
							| 
									
										
										
										
											2022-07-19 18:09:54 +08:00
										 |  |  | 			0, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			"simple indirect expand via single relation field (deprecated syntax)", | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"demo3", | 
					
						
							|  |  |  | 			"lcl9d87w22ml6jy", | 
					
						
							|  |  |  | 			[]string{"demo4(rel_one_no_cascade_required)"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			1, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			"simple indirect expand via single relation field", | 
					
						
							|  |  |  | 			"demo3", | 
					
						
							|  |  |  | 			"lcl9d87w22ml6jy", | 
					
						
							|  |  |  | 			[]string{"demo4_via_rel_one_no_cascade_required"}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			1, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"nested indirect expand via single relation field", | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			"demo3", | 
					
						
							|  |  |  | 			"lcl9d87w22ml6jy", | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"demo4(rel_one_no_cascade_required).self_rel_many.self_rel_many.self_rel_one", | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			5, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			"nested indirect expand via single relation field", | 
					
						
							|  |  |  | 			"demo3", | 
					
						
							|  |  |  | 			"lcl9d87w22ml6jy", | 
					
						
							|  |  |  | 			[]string{ | 
					
						
							|  |  |  | 				"demo4_via_rel_many_no_cascade_required.self_rel_many.rel_many_no_cascade_required.demo4_via_rel_many_no_cascade_required", | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 				return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			7, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | 	for _, s := range scenarios { | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		t.Run(s.testName, func(t *testing.T) { | 
					
						
							|  |  |  | 			record, _ := app.FindRecordById(s.collectionIdOrName, s.recordId) | 
					
						
							|  |  |  | 			failed := app.ExpandRecord(record, s.expands, s.fetchFunc) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			if len(failed) != s.expectExpandFailures { | 
					
						
							|  |  |  | 				t.Errorf("Expected %d failures, got %d\n%v", s.expectExpandFailures, len(failed), failed) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			encoded, _ := json.Marshal(record) | 
					
						
							|  |  |  | 			encodedStr := string(encoded) | 
					
						
							|  |  |  | 			totalExpandProps := strings.Count(encodedStr, `"`+core.FieldNameExpand+`":`) | 
					
						
							|  |  |  | 			totalEmptyExpands := strings.Count(encodedStr, `"`+core.FieldNameExpand+`":{}`) | 
					
						
							|  |  |  | 			totalNonemptyExpands := totalExpandProps - totalEmptyExpands | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 			if s.expectNonemptyExpandProps != totalNonemptyExpands { | 
					
						
							|  |  |  | 				t.Errorf("Expected %d expand props, got %d\n%v", s.expectNonemptyExpandProps, totalNonemptyExpands, encodedStr) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | func TestBackRelationExpandSingeVsArrayResult(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-01-03 10:30:20 +08:00
										 |  |  | 	t.Parallel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 	app, _ := tests.NewTestApp() | 
					
						
							|  |  |  | 	defer app.Cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 	record, err := app.FindRecordById("demo3", "7nwo8tuiatetxdm") | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// non-unique indirect expand
 | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		errs := app.ExpandRecord(record, []string{"demo4_via_rel_one_cascade"}, func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 			return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 		if len(errs) > 0 { | 
					
						
							|  |  |  | 			t.Fatal(errs) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		result, ok := record.Expand()["demo4_via_rel_one_cascade"].([]*core.Record) | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 		if !ok { | 
					
						
							|  |  |  | 			t.Fatalf("Expected the expanded result to be a slice, got %v", result) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 	// unique indirect expand
 | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 		// mock a unique constraint for the rel_one_cascade field
 | 
					
						
							|  |  |  | 		// ---
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		demo4, err := app.FindCollectionByNameOrId("demo4") | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		demo4.Indexes = append(demo4.Indexes, "create unique index idx_unique_expand on demo4 (rel_one_cascade)") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		if err := app.Save(demo4); err != nil { | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 			t.Fatalf("Failed to mock unique constraint: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-02-19 22:55:34 +08:00
										 |  |  | 		// ---
 | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		errs := app.ExpandRecord(record, []string{"demo4_via_rel_one_cascade"}, func(c *core.Collection, ids []string) ([]*core.Record, error) { | 
					
						
							|  |  |  | 			return app.FindRecordsByIds(c.Id, ids, nil) | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 		if len(errs) > 0 { | 
					
						
							|  |  |  | 			t.Fatal(errs) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 		result, ok := record.Expand()["demo4_via_rel_one_cascade"].(*core.Record) | 
					
						
							| 
									
										
										
										
											2023-03-22 03:38:28 +08:00
										 |  |  | 		if !ok { | 
					
						
							|  |  |  | 			t.Fatalf("Expected the expanded result to be a single model, got %v", result) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |