1const { resolve } = require('path') 2const t = require('tap') 3const { explainNode, printNode } = require('../../../lib/utils/explain-dep.js') 4const { cleanCwd } = require('../../fixtures/clean-snapshot') 5 6t.cleanSnapshot = (str) => cleanCwd(str) 7 8const getCases = (testdir) => { 9 const cases = { 10 prodDep: { 11 name: 'prod-dep', 12 version: '1.2.3', 13 location: 'node_modules/prod-dep', 14 dependents: [ 15 { 16 type: 'prod', 17 name: 'prod-dep', 18 spec: '1.x', 19 from: { 20 location: '/path/to/project', 21 }, 22 }, 23 ], 24 }, 25 26 deepDev: { 27 name: 'deep-dev', 28 version: '2.3.4', 29 location: 'node_modules/deep-dev', 30 dev: true, 31 dependents: [ 32 { 33 type: 'prod', 34 name: 'deep-dev', 35 spec: '2.x', 36 from: { 37 name: 'metadev', 38 version: '3.4.5', 39 location: 'node_modules/dev/node_modules/metadev', 40 dependents: [ 41 { 42 type: 'prod', 43 name: 'metadev', 44 spec: '3.x', 45 from: { 46 name: 'topdev', 47 version: '4.5.6', 48 location: 'node_modules/topdev', 49 dependents: [ 50 { 51 type: 'dev', 52 name: 'topdev', 53 spec: '4.x', 54 from: { 55 location: '/path/to/project', 56 }, 57 }, 58 ], 59 }, 60 }, 61 ], 62 }, 63 }, 64 ], 65 }, 66 67 optional: { 68 name: 'optdep', 69 version: '1.0.0', 70 location: 'node_modules/optdep', 71 optional: true, 72 dependents: [ 73 { 74 type: 'optional', 75 name: 'optdep', 76 spec: '1.0.0', 77 from: { 78 location: '/path/to/project', 79 }, 80 }, 81 ], 82 }, 83 84 peer: { 85 name: 'peer', 86 version: '1.0.0', 87 location: 'node_modules/peer', 88 peer: true, 89 dependents: [ 90 { 91 type: 'peer', 92 name: 'peer', 93 spec: '1.0.0', 94 from: { 95 location: '/path/to/project', 96 }, 97 }, 98 ], 99 }, 100 101 bundled: { 102 name: 'bundle-of-joy', 103 version: '1.0.0', 104 location: 'node_modules/bundle-of-joy', 105 bundled: true, 106 dependents: [ 107 { 108 type: 'prod', 109 name: 'prod-dep', 110 spec: '1.x', 111 bundled: true, 112 from: { 113 location: '/path/to/project', 114 }, 115 }, 116 ], 117 }, 118 119 extraneous: { 120 name: 'extra-neos', 121 version: '1337.420.69-lol', 122 location: 'node_modules/extra-neos', 123 dependents: [], 124 extraneous: true, 125 }, 126 127 overridden: { 128 name: 'overridden-root', 129 version: '1.0.0', 130 location: 'node_modules/overridden-root', 131 overridden: true, 132 dependents: [{ 133 type: 'prod', 134 name: 'overridden-dep', 135 spec: '1.0.0', 136 rawSpec: '^2.0.0', 137 overridden: true, 138 from: { 139 location: '/path/to/project', 140 }, 141 }], 142 }, 143 } 144 145 cases.manyDeps = { 146 name: 'manydep', 147 version: '1.0.0', 148 dependents: [ 149 { 150 type: 'prod', 151 name: 'manydep', 152 spec: '1.0.0', 153 from: cases.prodDep, 154 }, 155 { 156 type: 'optional', 157 name: 'manydep', 158 spec: '1.x', 159 from: cases.optional, 160 }, 161 { 162 type: 'prod', 163 name: 'manydep', 164 spec: '1.0.x', 165 from: cases.extraneous, 166 }, 167 { 168 type: 'dev', 169 name: 'manydep', 170 spec: '*', 171 from: cases.deepDev, 172 }, 173 { 174 type: 'peer', 175 name: 'manydep', 176 spec: '>1.0.0-beta <1.0.1', 177 from: cases.peer, 178 }, 179 { 180 type: 'prod', 181 name: 'manydep', 182 spec: '>1.0.0-beta <1.0.1', 183 from: { 184 location: '/path/to/project', 185 }, 186 }, 187 { 188 type: 'prod', 189 name: 'manydep', 190 spec: '1', 191 from: { 192 name: 'a package with a pretty long name', 193 version: '1.2.3', 194 dependents: { 195 location: '/path/to/project', 196 }, 197 }, 198 }, 199 { 200 type: 'prod', 201 name: 'manydep', 202 spec: '1', 203 from: { 204 name: 'another package with a pretty long name', 205 version: '1.2.3', 206 dependents: { 207 location: '/path/to/project', 208 }, 209 }, 210 }, 211 { 212 type: 'prod', 213 name: 'manydep', 214 spec: '1', 215 from: { 216 name: 'yet another a package with a pretty long name', 217 version: '1.2.3', 218 dependents: { 219 location: '/path/to/project', 220 }, 221 }, 222 }, 223 ], 224 } 225 226 cases.workspaces = { 227 name: 'a', 228 version: '1.0.0', 229 location: 'a', 230 isWorkspace: true, 231 dependents: [], 232 linksIn: [ 233 { 234 name: 'a', 235 version: '1.0.0', 236 location: 'node_modules/a', 237 isWorkspace: true, 238 dependents: [ 239 { 240 type: 'workspace', 241 name: 'a', 242 spec: `file:${resolve(testdir, 'ws-project', 'a')}`, 243 from: { location: resolve(testdir, 'ws-project') }, 244 }, 245 ], 246 }, 247 ], 248 } 249 250 return cases 251} 252 253t.test('basic', async t => { 254 const { Chalk } = await import('chalk') 255 const color = new Chalk({ level: 3 }) 256 const noColor = new Chalk({ level: 0 }) 257 258 const testdir = t.testdir() 259 const cases = getCases(testdir) 260 261 for (const [name, expl] of Object.entries(getCases(testdir))) { 262 t.test(name, t => { 263 t.matchSnapshot(printNode(expl, color), 'print color') 264 t.matchSnapshot(printNode(expl, noColor), 'print nocolor') 265 t.matchSnapshot(explainNode(expl, Infinity, color), 'explain color deep') 266 t.matchSnapshot(explainNode(expl, 2, noColor), 'explain nocolor shallow') 267 t.end() 268 }) 269 } 270 271 // make sure that we show the last one if it's the only one that would 272 // hit the ... 273 cases.manyDeps.dependents.pop() 274 t.matchSnapshot(explainNode(cases.manyDeps, 2, noColor), 'ellipses test one') 275 cases.manyDeps.dependents.pop() 276 t.matchSnapshot(explainNode(cases.manyDeps, 2, noColor), 'ellipses test two') 277}) 278