@vltpkg/query 1.0.0-rc.32 → 1.0.0-rc.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +10 -6
- package/dist/parser.js +2 -1
- package/dist/pseudo/hostname.js +3 -1
- package/dist/pseudo/malware.d.ts +3 -16
- package/dist/pseudo/malware.js +11 -171
- package/dist/pseudo/scripts.js +1 -1
- package/dist/pseudo/vuln.d.ts +22 -0
- package/dist/pseudo/vuln.js +220 -0
- package/dist/pseudo.js +3 -3
- package/dist/types.d.ts +3 -2
- package/package.json +19 -10
- package/skills/dss-query/REFERENCE.md +123 -0
- package/skills/dss-query/SKILL.md +190 -0
- package/skills/dss-query/evals/README.md +79 -0
- package/skills/dss-query/evals/evals.json +89 -0
- package/skills/dss-query/evals/grade.mjs +480 -0
- package/src/attribute.ts +186 -0
- package/src/combinator.ts +132 -0
- package/src/id.ts +46 -0
- package/src/index.ts +620 -0
- package/src/parser.ts +122 -0
- package/src/pseudo/abandoned.ts +9 -0
- package/src/pseudo/attr.ts +92 -0
- package/src/pseudo/built.ts +19 -0
- package/src/pseudo/confused.ts +29 -0
- package/src/pseudo/cve.ts +93 -0
- package/src/pseudo/cwe.ts +97 -0
- package/src/pseudo/debug.ts +9 -0
- package/src/pseudo/deprecated.ts +9 -0
- package/src/pseudo/dev.ts +18 -0
- package/src/pseudo/diff.ts +90 -0
- package/src/pseudo/dist.ts +144 -0
- package/src/pseudo/dynamic.ts +9 -0
- package/src/pseudo/empty.ts +15 -0
- package/src/pseudo/entropic.ts +9 -0
- package/src/pseudo/env.ts +6 -0
- package/src/pseudo/eval.ts +9 -0
- package/src/pseudo/fs.ts +9 -0
- package/src/pseudo/helpers.ts +106 -0
- package/src/pseudo/host.ts +111 -0
- package/src/pseudo/hostname.ts +156 -0
- package/src/pseudo/license.ts +134 -0
- package/src/pseudo/link.ts +30 -0
- package/src/pseudo/malware.ts +41 -0
- package/src/pseudo/minified.ts +9 -0
- package/src/pseudo/missing.ts +16 -0
- package/src/pseudo/native.ts +9 -0
- package/src/pseudo/network.ts +9 -0
- package/src/pseudo/obfuscated.ts +9 -0
- package/src/pseudo/optional.ts +18 -0
- package/src/pseudo/outdated.ts +305 -0
- package/src/pseudo/overridden.ts +20 -0
- package/src/pseudo/path.ts +146 -0
- package/src/pseudo/peer.ts +18 -0
- package/src/pseudo/prerelease.ts +47 -0
- package/src/pseudo/private.ts +19 -0
- package/src/pseudo/prod.ts +18 -0
- package/src/pseudo/published.ts +248 -0
- package/src/pseudo/registry.ts +29 -0
- package/src/pseudo/root.ts +19 -0
- package/src/pseudo/scanned.ts +20 -0
- package/src/pseudo/score.ts +186 -0
- package/src/pseudo/scripts.ts +54 -0
- package/src/pseudo/semver.ts +320 -0
- package/src/pseudo/severity.ts +231 -0
- package/src/pseudo/shell.ts +9 -0
- package/src/pseudo/shrinkwrap.ts +9 -0
- package/src/pseudo/spec.ts +131 -0
- package/src/pseudo/squat.ts +225 -0
- package/src/pseudo/suspicious.ts +9 -0
- package/src/pseudo/tracker.ts +9 -0
- package/src/pseudo/trivial.ts +9 -0
- package/src/pseudo/type.ts +26 -0
- package/src/pseudo/undesirable.ts +9 -0
- package/src/pseudo/unknown.ts +9 -0
- package/src/pseudo/unmaintained.ts +9 -0
- package/src/pseudo/unpopular.ts +9 -0
- package/src/pseudo/unstable.ts +9 -0
- package/src/pseudo/vuln.ts +273 -0
- package/src/pseudo/workspace.ts +22 -0
- package/src/pseudo.ts +413 -0
- package/src/types.ts +165 -0
- package/tap-snapshots/test/attribute.ts.test.cjs +304 -0
- package/tap-snapshots/test/combinator.ts.test.cjs +333 -0
- package/tap-snapshots/test/id.ts.test.cjs +118 -0
- package/tap-snapshots/test/parser.ts.test.cjs +344 -0
- package/tap-snapshots/test/pseudo/abandoned.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/attr.ts.test.cjs +161 -0
- package/tap-snapshots/test/pseudo/built.ts.test.cjs +70 -0
- package/tap-snapshots/test/pseudo/confused.ts.test.cjs +32 -0
- package/tap-snapshots/test/pseudo/cve.ts.test.cjs +49 -0
- package/tap-snapshots/test/pseudo/cwe.ts.test.cjs +49 -0
- package/tap-snapshots/test/pseudo/debug.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/deprecated.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/dist.ts.test.cjs +30 -0
- package/tap-snapshots/test/pseudo/dynamic.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/empty.ts.test.cjs +50 -0
- package/tap-snapshots/test/pseudo/entropic.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/env.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/eval.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/fs.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/helpers.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/hostname.ts.test.cjs +148 -0
- package/tap-snapshots/test/pseudo/license.ts.test.cjs +41 -0
- package/tap-snapshots/test/pseudo/link.ts.test.cjs +36 -0
- package/tap-snapshots/test/pseudo/malware.ts.test.cjs +22 -0
- package/tap-snapshots/test/pseudo/minified.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/missing.ts.test.cjs +30 -0
- package/tap-snapshots/test/pseudo/native.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/network.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/obfuscated.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/outdated.ts.test.cjs +130 -0
- package/tap-snapshots/test/pseudo/overridden.ts.test.cjs +75 -0
- package/tap-snapshots/test/pseudo/prerelease.ts.test.cjs +101 -0
- package/tap-snapshots/test/pseudo/private.ts.test.cjs +38 -0
- package/tap-snapshots/test/pseudo/published.ts.test.cjs +171 -0
- package/tap-snapshots/test/pseudo/registry.ts.test.cjs +68 -0
- package/tap-snapshots/test/pseudo/root.ts.test.cjs +24 -0
- package/tap-snapshots/test/pseudo/scanned.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/score.ts.test.cjs +239 -0
- package/tap-snapshots/test/pseudo/scripts.ts.test.cjs +61 -0
- package/tap-snapshots/test/pseudo/semver.ts.test.cjs +575 -0
- package/tap-snapshots/test/pseudo/severity.ts.test.cjs +95 -0
- package/tap-snapshots/test/pseudo/shell.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/shrinkwrap.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/spec.ts.test.cjs +148 -0
- package/tap-snapshots/test/pseudo/squat.ts.test.cjs +129 -0
- package/tap-snapshots/test/pseudo/suspicious.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/tracker.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/trivial.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/type.ts.test.cjs +51 -0
- package/tap-snapshots/test/pseudo/undesirable.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/unknown.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/unmaintained.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/unpopular.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/unstable.ts.test.cjs +18 -0
- package/tap-snapshots/test/pseudo/vuln.ts.test.cjs +208 -0
- package/tap-snapshots/test/pseudo/vulnerable.ts.test.cjs +20 -0
- package/tap-snapshots/test/pseudo/workspace.ts.test.cjs +19 -0
- package/tap-snapshots/test/pseudo.ts.test.cjs +1247 -0
- package/test/attribute.ts +266 -0
- package/test/combinator.ts +168 -0
- package/test/fixtures/graph.ts +999 -0
- package/test/fixtures/selector.ts +103 -0
- package/test/fixtures/types.ts +7 -0
- package/test/id.ts +102 -0
- package/test/index.ts +1000 -0
- package/test/parser.ts +117 -0
- package/test/pseudo/abandoned.ts +98 -0
- package/test/pseudo/attr.ts +298 -0
- package/test/pseudo/built.ts +214 -0
- package/test/pseudo/confused.ts +160 -0
- package/test/pseudo/cve.ts +249 -0
- package/test/pseudo/cwe.ts +255 -0
- package/test/pseudo/debug.ts +98 -0
- package/test/pseudo/deprecated.ts +98 -0
- package/test/pseudo/dev.ts +61 -0
- package/test/pseudo/diff.ts +417 -0
- package/test/pseudo/dist.ts +215 -0
- package/test/pseudo/dynamic.ts +98 -0
- package/test/pseudo/empty.ts +108 -0
- package/test/pseudo/entropic.ts +101 -0
- package/test/pseudo/env.ts +98 -0
- package/test/pseudo/eval.ts +98 -0
- package/test/pseudo/fs.ts +98 -0
- package/test/pseudo/helpers.ts +370 -0
- package/test/pseudo/host-context.ts +276 -0
- package/test/pseudo/hostname.ts +314 -0
- package/test/pseudo/license.ts +265 -0
- package/test/pseudo/link.ts +94 -0
- package/test/pseudo/malware.ts +184 -0
- package/test/pseudo/minified.ts +98 -0
- package/test/pseudo/missing.ts +111 -0
- package/test/pseudo/native.ts +98 -0
- package/test/pseudo/network.ts +98 -0
- package/test/pseudo/obfuscated.ts +98 -0
- package/test/pseudo/optional.ts +73 -0
- package/test/pseudo/outdated.ts +331 -0
- package/test/pseudo/overridden.ts +317 -0
- package/test/pseudo/path.ts +680 -0
- package/test/pseudo/peer.ts +101 -0
- package/test/pseudo/prerelease.ts +279 -0
- package/test/pseudo/private.ts +108 -0
- package/test/pseudo/prod.ts +61 -0
- package/test/pseudo/published.ts +557 -0
- package/test/pseudo/registry.ts +122 -0
- package/test/pseudo/root.ts +66 -0
- package/test/pseudo/scanned.ts +78 -0
- package/test/pseudo/score.ts +591 -0
- package/test/pseudo/scripts.ts +294 -0
- package/test/pseudo/semver.ts +822 -0
- package/test/pseudo/severity.ts +310 -0
- package/test/pseudo/shell.ts +98 -0
- package/test/pseudo/shrinkwrap.ts +98 -0
- package/test/pseudo/spec.ts +525 -0
- package/test/pseudo/squat.ts +565 -0
- package/test/pseudo/suspicious.ts +98 -0
- package/test/pseudo/tracker.ts +98 -0
- package/test/pseudo/trivial.ts +98 -0
- package/test/pseudo/type.ts +105 -0
- package/test/pseudo/undesirable.ts +98 -0
- package/test/pseudo/unknown.ts +98 -0
- package/test/pseudo/unmaintained.ts +98 -0
- package/test/pseudo/unpopular.ts +98 -0
- package/test/pseudo/unstable.ts +98 -0
- package/test/pseudo/vuln.ts +625 -0
- package/test/pseudo/vulnerable.ts +137 -0
- package/test/pseudo/workspace.ts +111 -0
- package/test/pseudo.ts +558 -0
- package/tsconfig.json +3 -0
- package/tsconfig.publish.json +19 -0
- package/tsconfig.publish.tsbuildinfo +1 -0
- package/typedoc.mjs +2 -0
- package/dist/pseudo/vulnerable.d.ts +0 -8
- package/dist/pseudo/vulnerable.js +0 -17
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { joinDepIDTuple } from '@vltpkg/dep-id'
|
|
2
|
+
import type { EdgeLike, NodeLike } from '@vltpkg/types'
|
|
3
|
+
import type { Attribute } from 'postcss-selector-parser'
|
|
4
|
+
import t from 'tap'
|
|
5
|
+
import {
|
|
6
|
+
attribute,
|
|
7
|
+
filterAttributes,
|
|
8
|
+
getManifestPropertyValues,
|
|
9
|
+
} from '../src/attribute.ts'
|
|
10
|
+
import {
|
|
11
|
+
getMissingNodeGraph,
|
|
12
|
+
getSimpleGraph,
|
|
13
|
+
} from './fixtures/graph.ts'
|
|
14
|
+
import {
|
|
15
|
+
copyGraphSelectionState,
|
|
16
|
+
getGraphSelectionState,
|
|
17
|
+
selectorFixture,
|
|
18
|
+
} from './fixtures/selector.ts'
|
|
19
|
+
import type { TestCase } from './fixtures/types.ts'
|
|
20
|
+
import type {
|
|
21
|
+
GraphSelectionState,
|
|
22
|
+
ParserState,
|
|
23
|
+
} from '../src/types.ts'
|
|
24
|
+
|
|
25
|
+
type ManifestLike = Record<string, any>
|
|
26
|
+
|
|
27
|
+
const testAttr = selectorFixture(attribute)
|
|
28
|
+
|
|
29
|
+
t.test('attribute', async t => {
|
|
30
|
+
const simpleGraph = getSimpleGraph()
|
|
31
|
+
const all: GraphSelectionState = {
|
|
32
|
+
edges: new Set<EdgeLike>(simpleGraph.edges),
|
|
33
|
+
nodes: new Set<NodeLike>(simpleGraph.nodes.values()),
|
|
34
|
+
}
|
|
35
|
+
const b = getGraphSelectionState(simpleGraph, 'b')
|
|
36
|
+
const empty: GraphSelectionState = {
|
|
37
|
+
edges: new Set(),
|
|
38
|
+
nodes: new Set(),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const queryToExpected = new Set<TestCase>([
|
|
42
|
+
[
|
|
43
|
+
'[version="1.0.0"]',
|
|
44
|
+
all,
|
|
45
|
+
['my-project', 'a', 'c', 'd', 'e', 'f', '@x/y'],
|
|
46
|
+
], // attribute matches all
|
|
47
|
+
[
|
|
48
|
+
'[name]',
|
|
49
|
+
all,
|
|
50
|
+
['my-project', 'a', 'b', 'c', 'd', 'e', 'f', '@x/y'],
|
|
51
|
+
], // attribute has any content
|
|
52
|
+
['[nonexistingattribute]', all, []], // non existing attribute
|
|
53
|
+
['[name="@x/y"]', all, ['@x/y']], // attribute matches scoped quoted
|
|
54
|
+
['[name^=m]', all, ['my-project']], // attribute starts with value
|
|
55
|
+
['[name^="m"]', all, ['my-project']], // attribute starts with value
|
|
56
|
+
['[name^=@x]', all, ['@x/y']], // attribute starts with scope
|
|
57
|
+
['[name^="@x"]', all, ['@x/y']], // attribute starts with scope
|
|
58
|
+
['[name$=project]', all, ['my-project']], // attribute ends with value
|
|
59
|
+
['[name$="project"]', all, ['my-project']], // attribute ends with value
|
|
60
|
+
['[name~=project]', all, ['my-project']], // attribute contains word
|
|
61
|
+
['[name~="project"]', all, ['my-project']], // attribute contains word
|
|
62
|
+
['[name~=notfound]', all, []], // attribute contains not found
|
|
63
|
+
['[name~="notfound"]', all, []], // attribute contains not found
|
|
64
|
+
['[name*=pro]', all, ['my-project']], // attribute contains string
|
|
65
|
+
['[name*="pro"]', all, ['my-project']], // attribute contains string
|
|
66
|
+
['[name|=my]', all, ['my-project']], // attribute starts with hyphened string
|
|
67
|
+
['[name|="my"]', all, ['my-project']], // attribute starts with hyphened string
|
|
68
|
+
['[name|="a"]', all, ['a']], // also matches on exact match
|
|
69
|
+
['[name="A"]', all, []], // case sensitive by default
|
|
70
|
+
['[name="A" i]', all, ['a']], // case insensitive flag
|
|
71
|
+
['[name="A" s]', all, []], // case insensitive flag
|
|
72
|
+
['[name="a"]', empty, []], // no matches if starting from empty partial
|
|
73
|
+
['[name="a"]', b, []], // no matches if node can't be find in partial
|
|
74
|
+
['[name="b"]', b, ['b']], // matches single node found
|
|
75
|
+
['[keywords=something]', all, ['c']], // matches item in array prop
|
|
76
|
+
['[keywords=missing]', all, []], // can not match missing item in array
|
|
77
|
+
])
|
|
78
|
+
const initial = {
|
|
79
|
+
edges: new Set(all.edges),
|
|
80
|
+
nodes: new Set(all.nodes),
|
|
81
|
+
}
|
|
82
|
+
for (const [query, partial, expected] of queryToExpected) {
|
|
83
|
+
const res = await testAttr(
|
|
84
|
+
query,
|
|
85
|
+
initial,
|
|
86
|
+
copyGraphSelectionState(partial),
|
|
87
|
+
)
|
|
88
|
+
t.strictSame(
|
|
89
|
+
res.nodes.map(i => i.name),
|
|
90
|
+
expected,
|
|
91
|
+
`query > "${query}"`,
|
|
92
|
+
)
|
|
93
|
+
t.matchSnapshot(
|
|
94
|
+
{
|
|
95
|
+
edges: res.edges.map(i => i.name).sort(),
|
|
96
|
+
nodes: res.nodes.map(i => i.name).sort(),
|
|
97
|
+
},
|
|
98
|
+
`query > "${query}"`,
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await t.test('missing node', async t => {
|
|
103
|
+
const missingNodeGraph = getMissingNodeGraph()
|
|
104
|
+
const all: GraphSelectionState = {
|
|
105
|
+
edges: new Set<EdgeLike>(missingNodeGraph.edges),
|
|
106
|
+
nodes: new Set<NodeLike>(missingNodeGraph.nodes.values()),
|
|
107
|
+
}
|
|
108
|
+
const queryToExpected = new Set<TestCase>([
|
|
109
|
+
['[name]', all, ['node-missing-project']], // root node has a name
|
|
110
|
+
['[name=a]', all, []], // can't match missing node
|
|
111
|
+
])
|
|
112
|
+
const initial = copyGraphSelectionState(all)
|
|
113
|
+
for (const [query, partial, expected] of queryToExpected) {
|
|
114
|
+
const res = await testAttr(
|
|
115
|
+
query,
|
|
116
|
+
initial,
|
|
117
|
+
copyGraphSelectionState(partial),
|
|
118
|
+
)
|
|
119
|
+
t.strictSame(
|
|
120
|
+
res.nodes.map(i => i.name),
|
|
121
|
+
expected,
|
|
122
|
+
`query > "${query}"`,
|
|
123
|
+
)
|
|
124
|
+
t.matchSnapshot(
|
|
125
|
+
{
|
|
126
|
+
edges: res.edges.map(i => i.name).sort(),
|
|
127
|
+
nodes: res.nodes.map(i => i.name).sort(),
|
|
128
|
+
},
|
|
129
|
+
`query > "${query}"`,
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
t.test('bad selector type', async t => {
|
|
136
|
+
await t.rejects(
|
|
137
|
+
testAttr(':dev'),
|
|
138
|
+
/Mismatching query node/,
|
|
139
|
+
'should throw an error',
|
|
140
|
+
)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
t.test('bad operator', async t => {
|
|
144
|
+
await t.rejects(
|
|
145
|
+
testAttr('[name==foo]'),
|
|
146
|
+
/Unsupported attribute operator: +=/,
|
|
147
|
+
'should throw an error',
|
|
148
|
+
)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
t.test('bad operator [loose mode]', async t => {
|
|
152
|
+
await t.resolves(
|
|
153
|
+
testAttr('[name==foo]', undefined, undefined, true),
|
|
154
|
+
'should resolve with no error',
|
|
155
|
+
)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
t.test(
|
|
159
|
+
'unquotted scoped names are not supported by the parser',
|
|
160
|
+
async t => {
|
|
161
|
+
await t.rejects(
|
|
162
|
+
testAttr('[name=@x/y]'),
|
|
163
|
+
/Unexpected "\/" found./,
|
|
164
|
+
'should throw an error',
|
|
165
|
+
)
|
|
166
|
+
},
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
t.test('getManifestPropertyValues', async t => {
|
|
170
|
+
const simpleGraph = getSimpleGraph()
|
|
171
|
+
const b = simpleGraph.nodes.get(
|
|
172
|
+
joinDepIDTuple(['registry', '', 'b@1.0.0']),
|
|
173
|
+
)!
|
|
174
|
+
|
|
175
|
+
t.strictSame(
|
|
176
|
+
getManifestPropertyValues(
|
|
177
|
+
b,
|
|
178
|
+
['scripts', 'postinstall'],
|
|
179
|
+
'postinstall',
|
|
180
|
+
),
|
|
181
|
+
['postinstall'],
|
|
182
|
+
'should return the postinstall script value',
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
t.strictSame(
|
|
186
|
+
getManifestPropertyValues(b, ['contributors'], 'contributors'),
|
|
187
|
+
['[object Object]'],
|
|
188
|
+
'should return a stringified object value',
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
t.strictSame(
|
|
192
|
+
getManifestPropertyValues(b, ['contributors', 'name'], 'name'),
|
|
193
|
+
['Ruy Adorno'],
|
|
194
|
+
'should return the value from a array-nested object',
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
b.manifest = { foo: 1 } as ManifestLike
|
|
198
|
+
t.strictSame(
|
|
199
|
+
getManifestPropertyValues(b, ['foo'], 'foo'),
|
|
200
|
+
['1'],
|
|
201
|
+
'should return values as strings',
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
b.manifest = { keywords: [undefined, 'foo'] } as ManifestLike
|
|
205
|
+
t.strictSame(
|
|
206
|
+
getManifestPropertyValues(b, ['keywords'], 'keywords'),
|
|
207
|
+
['', 'foo'],
|
|
208
|
+
'should turn falsy values into empty strings',
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
b.manifest = 'bad manifest' as unknown as ManifestLike
|
|
212
|
+
t.strictSame(
|
|
213
|
+
getManifestPropertyValues(b, ['name'], 'name'),
|
|
214
|
+
undefined,
|
|
215
|
+
'should not return results from a bad manifest',
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
delete b.manifest
|
|
219
|
+
t.strictSame(
|
|
220
|
+
getManifestPropertyValues(b, ['name'], 'name'),
|
|
221
|
+
undefined,
|
|
222
|
+
'should not return results from a missing manifest',
|
|
223
|
+
)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
t.test('filterAttributes', async t => {
|
|
227
|
+
const simpleGraph = getSimpleGraph()
|
|
228
|
+
const all: GraphSelectionState = {
|
|
229
|
+
edges: new Set<EdgeLike>(simpleGraph.edges),
|
|
230
|
+
nodes: new Set<NodeLike>(simpleGraph.nodes.values()),
|
|
231
|
+
}
|
|
232
|
+
const state = {
|
|
233
|
+
cancellable: async () => {},
|
|
234
|
+
collect: {
|
|
235
|
+
edges: new Set<EdgeLike>(),
|
|
236
|
+
nodes: new Set<NodeLike>(),
|
|
237
|
+
},
|
|
238
|
+
comment: '',
|
|
239
|
+
current: { type: 'attribute', value: 'postinstall' } as Attribute,
|
|
240
|
+
initial: copyGraphSelectionState(all),
|
|
241
|
+
partial: all,
|
|
242
|
+
loose: false,
|
|
243
|
+
importers: simpleGraph.importers,
|
|
244
|
+
hostContexts: new Map(),
|
|
245
|
+
walk: async (state: ParserState) => state,
|
|
246
|
+
retries: 0,
|
|
247
|
+
securityArchive: undefined,
|
|
248
|
+
signal: new AbortController().signal,
|
|
249
|
+
specificity: { idCounter: 0, commonCounter: 0 },
|
|
250
|
+
}
|
|
251
|
+
filterAttributes(
|
|
252
|
+
state,
|
|
253
|
+
(attr: string) => !!attr,
|
|
254
|
+
'postinstall',
|
|
255
|
+
'scripts',
|
|
256
|
+
false,
|
|
257
|
+
['scripts', 'postinstall'],
|
|
258
|
+
)
|
|
259
|
+
t.matchSnapshot(
|
|
260
|
+
{
|
|
261
|
+
edges: [...state.partial.edges].map(i => i.name).sort(),
|
|
262
|
+
nodes: [...state.partial.nodes].map(i => i.name).sort(),
|
|
263
|
+
},
|
|
264
|
+
'should have filtered out nodes with postinstall script only',
|
|
265
|
+
)
|
|
266
|
+
})
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import t from 'tap'
|
|
2
|
+
import { combinator } from '../src/combinator.ts'
|
|
3
|
+
import { walk } from '../src/index.ts'
|
|
4
|
+
import { getCycleGraph, getSimpleGraph } from './fixtures/graph.ts'
|
|
5
|
+
import {
|
|
6
|
+
copyGraphSelectionState,
|
|
7
|
+
getGraphSelectionState,
|
|
8
|
+
selectorFixture,
|
|
9
|
+
} from './fixtures/selector.ts'
|
|
10
|
+
import type { TestCase } from './fixtures/types.ts'
|
|
11
|
+
import type { EdgeLike, NodeLike } from '@vltpkg/types'
|
|
12
|
+
import type { GraphSelectionState } from '../src/types.ts'
|
|
13
|
+
|
|
14
|
+
const testCombinator = selectorFixture(combinator)
|
|
15
|
+
|
|
16
|
+
t.test('combinator', async t => {
|
|
17
|
+
const simpleGraph = getSimpleGraph()
|
|
18
|
+
const all: GraphSelectionState = {
|
|
19
|
+
edges: new Set<EdgeLike>(simpleGraph.edges),
|
|
20
|
+
nodes: new Set<NodeLike>(simpleGraph.nodes.values()),
|
|
21
|
+
}
|
|
22
|
+
const root = {
|
|
23
|
+
edges: new Set<EdgeLike>(),
|
|
24
|
+
nodes: new Set<NodeLike>([simpleGraph.mainImporter]),
|
|
25
|
+
}
|
|
26
|
+
const b = getGraphSelectionState(simpleGraph, 'b')
|
|
27
|
+
const d = getGraphSelectionState(simpleGraph, 'd')
|
|
28
|
+
const bd: GraphSelectionState = {
|
|
29
|
+
edges: new Set<EdgeLike>([...b.edges, ...d.edges]),
|
|
30
|
+
nodes: new Set<NodeLike>([...b.nodes, ...d.nodes]),
|
|
31
|
+
}
|
|
32
|
+
const e = getGraphSelectionState(simpleGraph, 'e')
|
|
33
|
+
const f = getGraphSelectionState(simpleGraph, 'f')
|
|
34
|
+
const empty: GraphSelectionState = {
|
|
35
|
+
edges: new Set(),
|
|
36
|
+
nodes: new Set(),
|
|
37
|
+
}
|
|
38
|
+
const queryToExpected = new Set<TestCase>([
|
|
39
|
+
// child combinator
|
|
40
|
+
['>', all, ['a', 'b', 'e', '@x/y', 'c', 'd', 'f']], // direct children of all nodes
|
|
41
|
+
['>', root, ['a', 'b', 'e', '@x/y']], // from root
|
|
42
|
+
['>', d, ['e', 'f']], // from transitive dep
|
|
43
|
+
['>', bd, ['c', 'd', 'e', 'f']], // from mutiple deps
|
|
44
|
+
['>', e, []], // from node with no deps
|
|
45
|
+
['>', empty, []], // from empty nodes
|
|
46
|
+
// subsequent sibling combinator
|
|
47
|
+
['~', all, ['b', 'e', '@x/y', 'a', 'd', 'c', 'f']], // siblings of all nodes
|
|
48
|
+
['~', f, ['e']], // leaf node with a sibling
|
|
49
|
+
['~', d, ['c']], // transitive node
|
|
50
|
+
['~', e, ['a', 'b', '@x/y', 'f']], // node with siblings at multiple locations
|
|
51
|
+
['~', root, []], // root has no siblings
|
|
52
|
+
['~', empty, []], // sibling of empty nodes
|
|
53
|
+
// descendent combinator
|
|
54
|
+
[' ', root, ['a', 'b', 'e', '@x/y', 'c', 'd', 'f']], // from root
|
|
55
|
+
[' ', f, []], // leaf node
|
|
56
|
+
[' ', empty, []], // empty list of nodes
|
|
57
|
+
[' ', d, ['e', 'f']], // transitive node
|
|
58
|
+
[' ', b, ['c', 'd', 'e', 'f']], // direct dep
|
|
59
|
+
])
|
|
60
|
+
const initial = copyGraphSelectionState(all)
|
|
61
|
+
for (const [query, partial, expected] of queryToExpected) {
|
|
62
|
+
const res = await testCombinator(
|
|
63
|
+
{ value: query, type: 'combinator' },
|
|
64
|
+
initial,
|
|
65
|
+
copyGraphSelectionState(partial),
|
|
66
|
+
)
|
|
67
|
+
t.strictSame(
|
|
68
|
+
res.nodes.map(i => i.name),
|
|
69
|
+
expected,
|
|
70
|
+
`query > "${query}"`,
|
|
71
|
+
)
|
|
72
|
+
t.matchSnapshot(
|
|
73
|
+
{
|
|
74
|
+
edges: res.edges.map(i => i.name).sort(),
|
|
75
|
+
nodes: res.nodes.map(i => i.name).sort(),
|
|
76
|
+
},
|
|
77
|
+
`query > "${query}"`,
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await t.test('cycle', async t => {
|
|
82
|
+
const cycleGraph = getCycleGraph()
|
|
83
|
+
const all: GraphSelectionState = {
|
|
84
|
+
edges: new Set<EdgeLike>(cycleGraph.edges),
|
|
85
|
+
nodes: new Set<NodeLike>(cycleGraph.nodes.values()),
|
|
86
|
+
}
|
|
87
|
+
const root = {
|
|
88
|
+
edges: new Set<EdgeLike>(),
|
|
89
|
+
nodes: new Set<NodeLike>([cycleGraph.mainImporter]),
|
|
90
|
+
}
|
|
91
|
+
const a = getGraphSelectionState(cycleGraph, 'a')
|
|
92
|
+
const b = getGraphSelectionState(cycleGraph, 'b')
|
|
93
|
+
const queryToExpected = new Set<TestCase>([
|
|
94
|
+
['>', all, ['a', 'b']], // direct children of all nodes
|
|
95
|
+
['>', a, ['b']], // direct children of a
|
|
96
|
+
['>', b, ['a']], // direct children of b
|
|
97
|
+
[' ', root, ['a', 'b']], // descendents of :root
|
|
98
|
+
[' ', a, ['b', 'a']], // descendents of a
|
|
99
|
+
[' ', b, ['a', 'b']], // descendents of b
|
|
100
|
+
['~', root, []], // siblings of :root
|
|
101
|
+
['~', a, []], // siblings of a
|
|
102
|
+
['~', b, []], // siblings of b
|
|
103
|
+
])
|
|
104
|
+
const initial = copyGraphSelectionState(all)
|
|
105
|
+
for (const [query, partial, expected] of queryToExpected) {
|
|
106
|
+
const result = await testCombinator(
|
|
107
|
+
{ value: query, type: 'combinator' },
|
|
108
|
+
initial,
|
|
109
|
+
copyGraphSelectionState(partial),
|
|
110
|
+
)
|
|
111
|
+
t.strictSame(
|
|
112
|
+
result.nodes.map(i => i.name),
|
|
113
|
+
expected,
|
|
114
|
+
`query > "${query}"`,
|
|
115
|
+
)
|
|
116
|
+
t.matchSnapshot(
|
|
117
|
+
{
|
|
118
|
+
edges: result.edges.map(i => i.name).sort(),
|
|
119
|
+
nodes: result.nodes.map(i => i.name).sort(),
|
|
120
|
+
},
|
|
121
|
+
`query > "${query}"`,
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// space between tags are not descendent combinators
|
|
127
|
+
await t.test('ignore spaces between tags', async t => {
|
|
128
|
+
const test = selectorFixture(walk)
|
|
129
|
+
const result = await test(
|
|
130
|
+
'* { * }',
|
|
131
|
+
all,
|
|
132
|
+
copyGraphSelectionState(all),
|
|
133
|
+
)
|
|
134
|
+
t.strictSame(
|
|
135
|
+
result.nodes.map(i => i.name),
|
|
136
|
+
[...all.nodes].map(i => i.name),
|
|
137
|
+
'should not treat spaces between tags as descendent combinators',
|
|
138
|
+
)
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
t.test('bad selector type', async t => {
|
|
143
|
+
await t.rejects(
|
|
144
|
+
testCombinator(':dev'),
|
|
145
|
+
/Mismatching query node/,
|
|
146
|
+
'should throw an error',
|
|
147
|
+
)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
t.test('usnupported combinator', async t => {
|
|
151
|
+
await t.rejects(
|
|
152
|
+
testCombinator({ value: '+', type: 'combinator' }),
|
|
153
|
+
/Unsupported combinator: \+/,
|
|
154
|
+
'should throw an error',
|
|
155
|
+
)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
t.test('usnupported combinator [loose mode]', async t => {
|
|
159
|
+
await t.resolves(
|
|
160
|
+
testCombinator(
|
|
161
|
+
{ value: '+', type: 'combinator' },
|
|
162
|
+
undefined,
|
|
163
|
+
undefined,
|
|
164
|
+
true,
|
|
165
|
+
),
|
|
166
|
+
'should resolve with no error',
|
|
167
|
+
)
|
|
168
|
+
})
|