@putout/test 15.0.0 → 15.1.0

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/README.md CHANGED
@@ -555,6 +555,58 @@ test('putout: processor: css: places', async ({comparePlaces}) => {
555
555
  });
556
556
  ```
557
557
 
558
+ ## Filesystem API
559
+
560
+ ```js
561
+ import {test} from '@putout/test/filesystem';
562
+ ```
563
+
564
+ ### `equalFilesystem(ast, expected)`
565
+
566
+ ```js
567
+ test('putout: operator: filesystem: findFile: exclude', (t) => {
568
+ const ast = parseFilesystem([
569
+ '/',
570
+ '/hello/',
571
+ '/hello/world.txt',
572
+ '/hello/hello.txt',
573
+ ]);
574
+
575
+ findFile(ast, '*.txt', ['hello.txt']).map(removeFile);
576
+
577
+ const expected = {
578
+ type: 'directory',
579
+ filename: '/',
580
+ files: [{
581
+ type: 'directory',
582
+ filename: '/hello',
583
+ files: [{
584
+ type: 'file',
585
+ filename: '/hello/hello.txt',
586
+ }],
587
+ }],
588
+ };
589
+
590
+ t.equalFilesystems(ast, expected);
591
+ t.end();
592
+ });
593
+ ```
594
+
595
+ ### `parseFilesystem(array)`
596
+
597
+ ```js
598
+ test('putout: operator: filesystem: writeFileContent: emoji', (t) => {
599
+ const ast = parseFilesystem(['/hello/world/', '/hello/world/README.md']);
600
+
601
+ const [filePath] = findFile(ast, 'README.md');
602
+ writeFileContent(filePath, 'hello 🐊');
603
+ const content = readFileContent(filePath);
604
+
605
+ t.equal(content, 'hello 🐊');
606
+ t.end();
607
+ });
608
+ ```
609
+
558
610
  ## License
559
611
 
560
612
  MIT
@@ -1,10 +1,9 @@
1
- 'use strict';
1
+ import {codeframe} from 'putout';
2
2
 
3
- const {codeframe} = require('putout');
4
3
  const {stringify} = JSON;
5
4
  const {entries} = Object;
6
5
 
7
- module.exports.createError = (help, source, values) => {
6
+ export const createError = (help, source, values) => {
8
7
  const argsBoxStart = '\n ╔══\n';
9
8
  const argsBoxLine = ' ║';
10
9
  const argsBoxEnd = '\n ╚══\n';
@@ -0,0 +1,53 @@
1
+ import {extend} from 'supertape';
2
+ import {parse, print} from 'putout';
3
+ import {
4
+ toJS,
5
+ fromJS,
6
+ __filesystem,
7
+ } from '@putout/operator-json';
8
+ import {parseSimpleFilesystem} from './parse-simple-filesystem.js';
9
+
10
+ const {isArray} = Array;
11
+ const {stringify} = JSON;
12
+
13
+ const PRINTER = ['putout', {
14
+ format: {
15
+ quote: '"',
16
+ endOfFile: '',
17
+ },
18
+ semantics: {
19
+ trailingComma: false,
20
+ },
21
+ }];
22
+
23
+ export const test = extend({
24
+ equalFilesystems: ({equal}) => (a, b) => {
25
+ return equal(printFilesystem(a), formatFilesystem(b));
26
+ },
27
+ filesystem: ({deepEqual}) => (a, b) => deepEqual(a, b),
28
+ });
29
+
30
+ export function parseFilesystem(fs) {
31
+ if (isArray(fs))
32
+ fs = parseSimpleFilesystem(fs);
33
+
34
+ const source = toJS(stringify(fs, null, 4), __filesystem);
35
+
36
+ return parse(source);
37
+ }
38
+
39
+ export function printFilesystem(ast) {
40
+ const source = print(ast, {
41
+ printer: PRINTER,
42
+ });
43
+
44
+ return fromJS(source, __filesystem);
45
+ }
46
+
47
+ export function formatFilesystem(fs) {
48
+ const source = print(parseFilesystem(fs), {
49
+ printer: PRINTER,
50
+ });
51
+
52
+ return fromJS(source, __filesystem);
53
+ }
@@ -0,0 +1,85 @@
1
+ import {dirname} from 'node:path';
2
+ import {operator} from 'putout';
3
+ import {parse, print} from '@putout/engine-parser';
4
+ import {toJS, fromJS} from '@putout/operator-json';
5
+ import {moveFile, findFile} from '@putout/operator-filesystem';
6
+
7
+ const {replaceWith} = operator;
8
+ const {isArray} = Array;
9
+ const {stringify} = JSON;
10
+
11
+ const noTrailingSlash = (a) => {
12
+ if (a === '/')
13
+ return a;
14
+
15
+ return a.endsWith('/') ? a.slice(0, -1) : a;
16
+ };
17
+
18
+ const createFile = (filename) => ({
19
+ type: 'file',
20
+ filename,
21
+ });
22
+
23
+ const createFileWithContent = (filename, content) => ({
24
+ type: 'file',
25
+ filename,
26
+ content,
27
+ });
28
+
29
+ const createDirectory = (filename) => ({
30
+ type: 'directory',
31
+ filename,
32
+ files: [],
33
+ });
34
+
35
+ const parseFirst = (a) => isArray(a) ? a[0] : a;
36
+
37
+ export const parseSimpleFilesystem = (list) => {
38
+ const files = createFlatFiles(list);
39
+ const js = toJS(stringify(files));
40
+ const ast = parse(js);
41
+
42
+ const filenames = list
43
+ .map(parseFirst)
44
+ .map(noTrailingSlash);
45
+
46
+ const [rootName] = filenames;
47
+
48
+ for (const filename of filenames) {
49
+ const [filePath] = findFile(ast, filename);
50
+ const dir = dirname(filename);
51
+ const [dirPath] = findFile(ast, dir);
52
+
53
+ if (!dirPath)
54
+ continue;
55
+
56
+ moveFile(filePath, dirPath);
57
+ }
58
+
59
+ const [rootPath] = findFile(ast, rootName);
60
+
61
+ replaceWith(rootPath.parentPath, rootPath);
62
+
63
+ return JSON.parse(fromJS(print(ast)));
64
+ };
65
+
66
+ function createFlatFiles(list) {
67
+ const result = [];
68
+
69
+ for (const file of list) {
70
+ if (isArray(file)) {
71
+ const [filename, content] = file;
72
+ result.push(createFileWithContent(filename, content));
73
+ continue;
74
+ }
75
+
76
+ if (file.endsWith('/')) {
77
+ result.push(createDirectory(noTrailingSlash(file)));
78
+ continue;
79
+ }
80
+
81
+ result.push(createFile(file));
82
+ }
83
+
84
+ return result;
85
+ }
package/lib/fixture.js CHANGED
@@ -1,7 +1,5 @@
1
- 'use strict';
2
-
3
- const process = require('node:process');
4
- const {tryCatch} = require('try-catch');
1
+ import process from 'node:process';
2
+ import {tryCatch} from 'try-catch';
5
3
 
6
4
  const isUpdate = () => Boolean(Number(process.env.UPDATE));
7
5
  const TS = {
@@ -9,7 +7,7 @@ const TS = {
9
7
  DISABLED: false,
10
8
  };
11
9
 
12
- module.exports.readFixture = (name, extension) => {
10
+ export const readFixture = (name, extension) => {
13
11
  const {readFileSync} = globalThis.__putout_test_fs;
14
12
  const [eTS, dataTS] = tryCatch(readFileSync, `${name}.ts`, 'utf8');
15
13
 
@@ -43,27 +41,27 @@ module.exports.readFixture = (name, extension) => {
43
41
  throw eJS;
44
42
  };
45
43
 
46
- module.exports.writeFixFixture = ({full, code, extension}) => {
44
+ export const writeFixFixture = ({full, code, extension}) => {
47
45
  const {writeFileSync} = globalThis.__putout_test_fs;
48
46
  writeFileSync(`${full}-fix.${extension}`, code);
49
47
  };
50
48
 
51
- module.exports.writeFormatFixture = (full, code) => {
49
+ export const writeFormatFixture = (full, code) => {
52
50
  const {writeFileSync} = globalThis.__putout_test_fs;
53
51
  writeFileSync(`${full}-format`, code);
54
52
  };
55
53
 
56
- module.exports.readFormatFixture = (full) => {
54
+ export const readFormatFixture = (full) => {
57
55
  const {readFileSync} = globalThis.__putout_test_fs;
58
56
  return readFileSync(`${full}-format`, 'utf8');
59
57
  };
60
58
 
61
- module.exports.writeFixture = ({full, code, extension}) => {
59
+ export const writeFixture = ({full, code, extension}) => {
62
60
  const {writeFileSync} = globalThis.__putout_test_fs;
63
61
  writeFileSync(`${full}.${extension}`, code);
64
62
  };
65
63
 
66
- module.exports.rmFixture = (name, extension) => {
64
+ export const rmFixture = (name, extension) => {
67
65
  const {unlinkSync} = globalThis.__putout_test_fs;
68
66
 
69
67
  if (!isUpdate())
@@ -1,22 +1,18 @@
1
- 'use strict';
2
-
3
- const process = require('node:process');
4
- const {join} = require('node:path');
5
-
6
- const putout = require('putout');
7
- const currify = require('currify');
8
- const {initReport} = require('@putout/engine-reporter/report');
9
-
10
- const {
1
+ import process from 'node:process';
2
+ import {join} from 'node:path';
3
+ import putout from 'putout';
4
+ import currify from 'currify';
5
+ import {initReport} from '@putout/engine-reporter/report';
6
+ import {
11
7
  readFixture,
12
8
  writeFormatFixture,
13
9
  readFormatFixture,
14
- } = require('../fixture');
10
+ } from '../fixture.js';
15
11
 
16
12
  const isUpdate = () => Boolean(Number(process.env.UPDATE));
17
13
  const {isArray} = Array;
18
14
 
19
- module.exports.format = currify((dir, options, t) => async (formatter, name, formatterOptions = {}) => {
15
+ export const format = currify((dir, options, t) => async (formatter, name, formatterOptions = {}) => {
20
16
  const full = join(dir, name);
21
17
  const [input, isTS] = readFixture(full);
22
18
 
@@ -51,7 +47,7 @@ module.exports.format = currify((dir, options, t) => async (formatter, name, for
51
47
  };
52
48
  });
53
49
 
54
- module.exports.noFormat = currify((dir, options, t) => async (formatter, name, formatterOptions = {}) => {
50
+ export const noFormat = currify((dir, options, t) => async (formatter, name, formatterOptions = {}) => {
55
51
  const full = join(dir, name);
56
52
  const [input] = readFixture(full);
57
53
  const {places} = putout(input, options);
@@ -73,7 +69,7 @@ module.exports.noFormat = currify((dir, options, t) => async (formatter, name, f
73
69
  };
74
70
  });
75
71
 
76
- module.exports.formatMany = currify((dir, options, t) => async (formatter, names, formatterOptions = {}) => {
72
+ export const formatMany = currify((dir, options, t) => async (formatter, names, formatterOptions = {}) => {
77
73
  const joinTwo = (a) => (b) => join(a, b);
78
74
 
79
75
  if (!isArray(names))
@@ -1,10 +1,8 @@
1
- 'use strict';
2
-
3
1
  const isFn = (a) => typeof a === 'function';
4
2
 
5
- module.exports.getIsCorrectPluginMessage = () => `should export 'replace', 'find', 'traverse', 'include', 'exclude', 'declare' or 'scan' function`;
3
+ export const getIsCorrectPluginMessage = () => `should export 'replace', 'find', 'traverse', 'include', 'exclude', 'declare' or 'scan' function`;
6
4
 
7
- module.exports.isCorrectPlugin = (plugin) => {
5
+ export const isCorrectPlugin = (plugin) => {
8
6
  const {
9
7
  find,
10
8
  fix,
@@ -0,0 +1,11 @@
1
+ import {fileURLToPath} from 'node:url';
2
+ import {dirname} from 'node:path';
3
+
4
+ export function maybeDirectory(url) {
5
+ if (url.startsWith('file:')) {
6
+ const __filename = fileURLToPath(url);
7
+ return dirname(__filename);
8
+ }
9
+
10
+ return url;
11
+ }
package/lib/pre-test.js CHANGED
@@ -1,9 +1,7 @@
1
- 'use strict';
2
-
3
- const {
1
+ import {
4
2
  isCorrectPlugin,
5
3
  getIsCorrectPluginMessage,
6
- } = require('./is-correct-plugin');
4
+ } from './is-correct-plugin.js';
7
5
 
8
6
  const {entries} = Object;
9
7
  const {isArray} = Array;
@@ -11,10 +9,10 @@ const {isArray} = Array;
11
9
  const maybeTuple = (a) => isArray(a) ? a : ['on', a];
12
10
  const maybeEntries = (a) => isArray(a) ? a : entries(a).pop();
13
11
 
14
- module.exports._maybeEntries = maybeEntries;
15
- module.exports._maybeTuple = maybeTuple;
12
+ export const _maybeEntries = maybeEntries;
13
+ export const _maybeTuple = maybeTuple;
16
14
 
17
- module.exports.preTest = function preTest(test, plugin) {
15
+ export function preTest(test, plugin) {
18
16
  const [name, {
19
17
  report,
20
18
  find,
@@ -82,4 +80,4 @@ module.exports.preTest = function preTest(test, plugin) {
82
80
  t.ok(result, getIsCorrectPluginMessage());
83
81
  t.end();
84
82
  }, options);
85
- };
83
+ }
@@ -1,22 +1,18 @@
1
- 'use strict';
2
-
3
- const {
1
+ import {
4
2
  readFile,
5
3
  writeFile,
6
4
  unlink,
7
- } = require('node:fs/promises');
8
-
9
- const {
5
+ } from 'node:fs/promises';
6
+ import {
10
7
  join,
11
8
  extname,
12
9
  basename,
13
- } = require('node:path');
14
-
15
- const {tryToCatch} = require('try-to-catch');
16
-
17
- const test = require('supertape');
18
- const {initProcessFile} = require('@putout/cli-process-file');
19
- const {runProcessors} = require('@putout/engine-processor');
10
+ } from 'node:path';
11
+ import {tryToCatch} from 'try-to-catch';
12
+ import test from 'supertape';
13
+ import {initProcessFile} from '@putout/cli-process-file';
14
+ import {runProcessors} from '@putout/engine-processor';
15
+ import {maybeDirectory} from '../maybe-directory.js';
20
16
 
21
17
  const isStr = (a) => typeof a === 'string';
22
18
  const isUpdate = () => Number(globalThis.process.env.UPDATE);
@@ -52,9 +48,11 @@ const fail = (t, message) => {
52
48
  return __putout_test_fail(message);
53
49
  };
54
50
 
55
- module.exports._addDot = addDot;
51
+ export const _addDot = addDot;
56
52
 
57
- module.exports.createTest = (dir, options) => {
53
+ export const createTest = (url, options) => {
54
+ const dir = maybeDirectory(url);
55
+
58
56
  return test.extend({
59
57
  process: createProcess(dir, options),
60
58
  noProcess: createNoProcess(dir, options),
@@ -89,7 +87,7 @@ const createProcess = (dir, options) => (operator) => async (filename, plugins,
89
87
  return operator.equal(processedSource, output, 'fixtures should equal');
90
88
  };
91
89
 
92
- module.exports._createProcess = createProcess;
90
+ export const _createProcess = createProcess;
93
91
 
94
92
  const createNoProcess = (dir, options) => (operator) => async (filename, plugins, processors) => {
95
93
  if (!isStr(filename))
@@ -110,7 +108,7 @@ const createNoProcess = (dir, options) => (operator) => async (filename, plugins
110
108
  return operator.equal(processedSource, rawSource, 'fixtures should equal');
111
109
  };
112
110
 
113
- module.exports._createNoProcess = createNoProcess;
111
+ export const _createNoProcess = createNoProcess;
114
112
 
115
113
  const createComparePlaces = (dir, options) => (operator) => async (filename, expectedPlaces) => {
116
114
  if (!isStr(filename))
@@ -124,7 +122,7 @@ const createComparePlaces = (dir, options) => (operator) => async (filename, exp
124
122
  return operator.deepEqual(places, expectedPlaces, 'places should equal');
125
123
  };
126
124
 
127
- module.exports._createComparePlaces = createComparePlaces;
125
+ export const _createComparePlaces = createComparePlaces;
128
126
 
129
127
  async function process(filename, dir, config) {
130
128
  let {extension} = config;
package/lib/test.js CHANGED
@@ -1,36 +1,30 @@
1
- 'use strict';
2
-
3
- const process = require('node:process');
4
- const {join} = require('node:path');
5
- const {once} = require('node:events');
6
-
7
- const {
1
+ import process from 'node:process';
2
+ import {join} from 'node:path';
3
+ import {once} from 'node:events';
4
+ import {
8
5
  readFileSync,
9
6
  writeFileSync,
10
7
  existsSync,
11
8
  unlinkSync,
12
- } = require('node:fs');
13
-
14
- const test = require('supertape');
15
- const putout = require('putout');
16
- const currify = require('currify');
17
- const {createProgress} = require('@putout/engine-runner/progress');
18
-
19
- const {createError} = require('./create-error');
20
- const {preTest} = require('./pre-test');
21
-
22
- const {
9
+ } from 'node:fs';
10
+ import test from 'supertape';
11
+ import putout from 'putout';
12
+ import currify from 'currify';
13
+ import {createProgress} from '@putout/engine-runner/progress';
14
+ import {createError} from './create-error.js';
15
+ import {preTest} from './pre-test.js';
16
+ import {
23
17
  format,
24
18
  noFormat,
25
19
  formatMany,
26
- } = require('./format');
27
-
28
- const {
20
+ } from './format/index.js';
21
+ import {maybeDirectory} from './maybe-directory.js';
22
+ import {
29
23
  readFixture,
30
24
  writeFixture,
31
25
  writeFixFixture,
32
26
  rmFixture,
33
- } = require('./fixture');
27
+ } from './fixture.js';
34
28
 
35
29
  const {isArray} = Array;
36
30
  const isString = (a) => typeof a === 'string';
@@ -55,8 +49,7 @@ const fail = (t, message) => {
55
49
  return __putout_test_fail(message);
56
50
  };
57
51
 
58
- module.exports = createTest;
59
- module.exports.createTest = createTest;
52
+ export default createTest;
60
53
 
61
54
  const parsePlugin = (plugins) => {
62
55
  if (isArray(plugins))
@@ -65,9 +58,8 @@ const parsePlugin = (plugins) => {
65
58
  return plugins;
66
59
  };
67
60
 
68
- function createTest(dir, maybeOptions, maybeExtends = {}) {
69
- dir = join(dir, 'fixture');
70
-
61
+ export function createTest(url, maybeOptions, maybeExtends = {}) {
62
+ const dir = join(maybeDirectory(url), 'fixture');
71
63
  const {
72
64
  extension = '',
73
65
  lint = putout,
@@ -359,7 +351,7 @@ const noReport = (dir, linterOptions, options) => (t) => (name, addons = []) =>
359
351
  }, t, source);
360
352
  };
361
353
 
362
- module.exports._createNoReport = noReport;
354
+ export const _createNoReport = noReport;
363
355
 
364
356
  const noReportAfterTransform = currify((dir, linterOptions, options, t, name, addons = {}) => {
365
357
  const {lint, extension} = linterOptions;
@@ -372,7 +364,7 @@ const noReportAfterTransform = currify((dir, linterOptions, options, t, name, ad
372
364
  }, t, source, addons);
373
365
  });
374
366
 
375
- module.exports._createNoReportAfterTransform = noReportAfterTransform;
367
+ export const _createNoReportAfterTransform = noReportAfterTransform;
376
368
 
377
369
  const noReportAfterTransformWithOptions = currify((dir, linterOptions, options, t, name, ruleOptions) => {
378
370
  const {lint, extension} = linterOptions;
@@ -394,7 +386,7 @@ const noReportAfterTransformWithOptions = currify((dir, linterOptions, options,
394
386
  }, t, source);
395
387
  });
396
388
 
397
- module.exports._createNoReportAfterTransformWithOptions = noReportAfterTransformWithOptions;
389
+ export const _createNoReportAfterTransformWithOptions = noReportAfterTransformWithOptions;
398
390
 
399
391
  const reportWithOptions = currify((dir, linterOptions, options, t, name, message, ruleOptions) => {
400
392
  const {lint, extension} = linterOptions;
package/package.json CHANGED
@@ -1,24 +1,19 @@
1
1
  {
2
2
  "name": "@putout/test",
3
- "version": "15.0.0",
4
- "type": "commonjs",
3
+ "version": "15.1.0",
4
+ "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "Test runner for 🐊Putout plugins ",
7
7
  "homepage": "https://github.com/coderaiser/putout/tree/master/packages/test#readme",
8
8
  "main": "lib/test.js",
9
9
  "bin": {
10
- "tape": "bin/test.mjs"
10
+ "tape": "bin/test.js"
11
11
  },
12
12
  "exports": {
13
- ".": {
14
- "require": "./lib/test.js",
15
- "import": "./lib/test.mjs"
16
- },
17
- "./processor": {
18
- "require": "./lib/processor/index.js",
19
- "import": "./lib/processor/index.mjs"
20
- },
21
- "./eslint": "./lib/eslint/eslint.mjs"
13
+ ".": "./lib/test.js",
14
+ "./processor": "./lib/processor/index.js",
15
+ "./eslint": "./lib/eslint/eslint.js",
16
+ "./filesystem": "./lib/filesystem/index.js"
22
17
  },
23
18
  "release": false,
24
19
  "tag": false,
@@ -39,15 +34,18 @@
39
34
  },
40
35
  "dependencies": {
41
36
  "@putout/cli-process-file": "^6.0.0",
37
+ "@putout/engine-parser": "^15.0.7",
42
38
  "@putout/engine-processor": "*",
43
39
  "@putout/engine-reporter": "^8.0.1",
44
40
  "@putout/engine-runner": "*",
45
41
  "@putout/eslint": "^5.0.0",
42
+ "@putout/operator-filesystem": "^10.0.4",
43
+ "@putout/operator-json": "^3.1.0",
46
44
  "@putout/plugin-filesystem": "*",
47
45
  "currify": "^4.0.0",
48
46
  "montag": "^1.2.1",
49
47
  "putout": "*",
50
- "supertape": "^11.0.3",
48
+ "supertape": "^12.0.0",
51
49
  "try-catch": "^4.0.0",
52
50
  "try-to-catch": "^4.0.0"
53
51
  },
@@ -72,7 +70,7 @@
72
70
  "eslint": "^10.0.0-alpha.0",
73
71
  "eslint-plugin-n": "^17.0.0",
74
72
  "eslint-plugin-putout": "^29.0.0",
75
- "madrun": "^11.0.0",
73
+ "madrun": "^12.0.0",
76
74
  "nodemon": "^3.0.1"
77
75
  },
78
76
  "license": "MIT",
@@ -1,10 +0,0 @@
1
- import {dirname} from 'node:path';
2
- import {fileURLToPath} from 'node:url';
3
- import * as processor from './index.js';
4
-
5
- export const createTest = (url, plugins) => {
6
- const __filename = fileURLToPath(url);
7
- const __dirname = dirname(__filename);
8
-
9
- return processor.createTest(__dirname, plugins);
10
- };
package/lib/test.mjs DELETED
@@ -1,12 +0,0 @@
1
- import {dirname} from 'node:path';
2
- import {fileURLToPath} from 'node:url';
3
- import create from './test.js';
4
-
5
- export default create;
6
-
7
- export const createTest = (url, plugins, maybeExtends) => {
8
- const __filename = fileURLToPath(url);
9
- const __dirname = dirname(__filename);
10
-
11
- return create(__dirname, plugins, maybeExtends);
12
- };
File without changes
File without changes