-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathdoctor-refs.test.ts
More file actions
145 lines (135 loc) · 4.75 KB
/
Copy pathdoctor-refs.test.ts
File metadata and controls
145 lines (135 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright (c) 2026 ObjectStack contributors. Apache-2.0 license.
//
// `os doctor` reference analysis (15.1 third-party eval): the collector only
// read the legacy flat `view.object` / `nav.object` shapes, so an object
// bound through a defineView container (`list.data.object`, `listViews[*]`)
// and hung on app navigation (`objectName`) was still reported as
// "defined but not referenced". These fixtures pin the canonical shapes.
import { describe, it, expect } from 'vitest';
import { findUnusedObjects, findOrphanViews } from '../src/commands/doctor';
const obj = (name: string, fields: Record<string, unknown> = { title: { type: 'text', label: 'T' } }) => ({
name,
label: name,
fields,
});
describe('findUnusedObjects', () => {
it('sees objects bound through defineView containers (list / listViews / form)', () => {
const config = {
objects: [obj('crm_account'), obj('crm_contact'), obj('crm_lead')],
views: [
{ list: { type: 'grid', data: { provider: 'object', object: 'crm_account' } } },
{
listViews: {
recent: { type: 'grid', data: { provider: 'object', object: 'crm_contact' } },
},
},
{ form: { data: { provider: 'object', object: 'crm_lead' } } },
],
};
expect(findUnusedObjects(config)).toEqual([]);
});
it('sees app navigation objectName, nested children, and areas', () => {
const config = {
objects: [obj('crm_account'), obj('crm_contact'), obj('crm_case')],
apps: [
{
name: 'crm',
navigation: [
{ type: 'object', objectName: 'crm_account' },
{
type: 'group',
label: 'More',
children: [{ type: 'object', objectName: 'crm_contact' }],
},
],
areas: [
{ name: 'service', navigation: [{ type: 'object', objectName: 'crm_case' }] },
],
},
],
};
expect(findUnusedObjects(config)).toEqual([]);
});
it('sees the object inside flow node config (record_change trigger / CRUD nodes)', () => {
const config = {
objects: [obj('crm_order')],
flows: [
{
name: 'on_order_change',
nodes: [{ id: 't1', type: 'record_change', config: { object: 'crm_order' } }],
},
],
};
expect(findUnusedObjects(config)).toEqual([]);
});
it('sees subform childObject and lookup form-field references', () => {
const config = {
objects: [obj('crm_order'), obj('crm_order_line'), obj('crm_account')],
views: [
{
list: { type: 'grid', data: { provider: 'object', object: 'crm_order' } },
form: {
data: { provider: 'object', object: 'crm_order' },
subforms: [{ field: 'lines', childObject: 'crm_order_line' }],
sections: [
{ fields: [{ name: 'account', type: 'lookup', reference: 'crm_account' }] },
],
},
},
],
};
expect(findUnusedObjects(config)).toEqual([]);
});
it('still reads legacy flat ViewItems and lookup fields', () => {
const config = {
objects: [
obj('crm_account'),
obj('crm_contact', {
account: { type: 'lookup', reference: 'crm_account', label: 'Account' },
}),
],
views: [{ name: 'contacts', object: 'crm_contact' }],
};
expect(findUnusedObjects(config)).toEqual([]);
});
it('still reports a genuinely unreferenced object', () => {
const config = {
objects: [obj('crm_account'), obj('crm_orphan')],
views: [{ list: { type: 'grid', data: { provider: 'object', object: 'crm_account' } } }],
};
const unused = findUnusedObjects(config);
expect(unused).toHaveLength(1);
expect(unused[0]).toContain('"crm_orphan"');
});
});
describe('findOrphanViews', () => {
it('reports container sub-views bound to non-existent objects', () => {
const config = {
objects: [obj('crm_account')],
views: [
{ list: { type: 'grid', data: { provider: 'object', object: 'crm_account' } } },
{
listViews: {
ghosts: { type: 'grid', data: { provider: 'object', object: 'crm_ghost' } },
},
},
],
};
const orphans = findOrphanViews(config);
expect(orphans).toHaveLength(1);
expect(orphans[0]).toContain('"crm_ghost"');
expect(orphans[0]).toContain('listViews.ghosts');
});
it('passes healthy containers and non-object providers', () => {
const config = {
objects: [obj('crm_account')],
views: [
{
list: { type: 'grid', data: { provider: 'object', object: 'crm_account' } },
form: { data: { provider: 'schema', schemaId: 'report' } },
},
],
};
expect(findOrphanViews(config)).toEqual([]);
});
});