diff --git a/.gitignore b/.gitignore index 445c3f14d..1c9775de0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ node_modules dist test/regression-fixtures test/regression-diffs +test/cli/output coverage .DS_Store *.log diff --git a/package.json b/package.json index 03d0ea3b0..f37fc6aa1 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,6 @@ "del": "^6.0.0", "eslint": "^7.32.0", "jest": "^27.2.5", - "mock-stdin": "^1.0.0", "node-fetch": "^2.6.2", "pixelmatch": "^5.2.1", "playwright": "^1.14.1", diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index c85263db8..6094b476e 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -1,7 +1,90 @@ 'use strict'; +/** + * @typedef {import('child_process').ChildProcessWithoutNullStreams} ChildProcessWithoutNullStreams + */ + +const fs = require('fs'); +const path = require('path'); const { spawn } = require('child_process'); +/** + * @type {(proc: ChildProcessWithoutNullStreams) => Promise} + */ +const waitStdout = (proc) => { + return new Promise((resolve) => { + proc.stdout.on('data', (data) => { + resolve(data.toString()); + }); + }); +}; + +/** + * @type {(proc: ChildProcessWithoutNullStreams) => Promise} + */ +const waitClose = (proc) => { + return new Promise((resolve) => { + proc.on('close', () => { + resolve(); + }); + }); +}; + +test('shows plugins when flag specified', async () => { + const proc = spawn( + 'node', + ['../../bin/svgo', '--no-color', '--show-plugins'], + { cwd: __dirname } + ); + const stdout = await waitStdout(proc); + expect(stdout).toMatch(/Currently available plugins:/); +}); + +test('accepts svg as input stream', async () => { + const proc = spawn('node', ['../../bin/svgo', '--no-color', '-'], { + cwd: __dirname, + }); + proc.stdin.write('stdin'); + proc.stdin.end(); + const stdout = await waitStdout(proc); + expect(stdout).toEqual('\n'); +}); + +test('accepts svg as string', async () => { + const input = 'string'; + const proc = spawn( + 'node', + ['../../bin/svgo', '--no-color', '--string', input], + { cwd: __dirname } + ); + const stdout = await waitStdout(proc); + expect(stdout).toEqual('\n'); +}); + +test('accepts svg as filename', async () => { + const proc = spawn( + 'node', + ['../../bin/svgo', '--no-color', 'single.svg', '-o', 'output/single.svg'], + { cwd: __dirname } + ); + await waitClose(proc); + const output = fs.readFileSync( + path.join(__dirname, 'output/single.svg'), + 'utf-8' + ); + expect(output).toEqual(''); +}); + +test('output as stream when "-" is specified', async () => { + const proc = spawn( + 'node', + ['../../bin/svgo', '--no-color', 'single.svg', '-o', '-'], + { cwd: __dirname } + ); + const stdout = await waitStdout(proc); + expect(stdout).toEqual('\n'); +}); + test('should exit with 1 code on syntax error', async () => { const proc = spawn('node', ['../../bin/svgo', '--no-color', 'invalid.svg'], { cwd: __dirname, diff --git a/test/cli/single.svg b/test/cli/single.svg new file mode 100644 index 000000000..54ee0d6be --- /dev/null +++ b/test/cli/single.svg @@ -0,0 +1 @@ +input diff --git a/test/coa/_index.test.js b/test/coa/_index.test.js index d41e3ed95..43bb9bf8a 100644 --- a/test/coa/_index.test.js +++ b/test/coa/_index.test.js @@ -6,7 +6,6 @@ const del = require('del'); const { Command } = require('commander'); const svgo = require('../../lib/svgo/coa.js'); -const svgPath = path.resolve(__dirname, 'test.svg'); const svgFolderPath = path.resolve(__dirname, 'testSvg'); const svgFolderPathRecursively = path.resolve(__dirname, 'testSvgRecursively'); const svgFiles = [ @@ -28,10 +27,7 @@ function runProgram(args) { } describe('coa', function () { - let output; - beforeEach(async () => { - output = ''; await del(tempFolder); await fs.promises.mkdir(tempFolder); }); @@ -40,25 +36,10 @@ describe('coa', function () { await del(tempFolder); }); - const initialConsoleLog = global.console.log; - - function replaceConsoleLog() { - global.console.log = (message) => { - output += message; - }; - } - - function restoreConsoleLog() { - global.console.log = initialConsoleLog; - } - const initialConsoleError = global.console.error; const initialProcessExit = global.process.exit; function replaceConsoleError() { - global.console.error = (message) => { - output += message; - }; global.process.exit = noop; } @@ -83,17 +64,6 @@ describe('coa', function () { ); } - it('should work properly with string input', async () => { - await runProgram([ - '--string', - fs.readFileSync(svgPath, 'utf8'), - '--output', - 'temp.svg', - '--quiet', - ]); - await del('temp.svg'); - }); - it('should optimize folder', async () => { const initWeight = calcFolderSvgWeight(svgFolderPath); await runProgram([ @@ -123,16 +93,6 @@ describe('coa', function () { expect(initWeight).toBeLessThanOrEqual(optimizedWeight); }); - it('should optimize file', async () => { - const initialFileLength = fs.readFileSync( - path.resolve(__dirname, 'test.svg') - ).length; - await runProgram(['--input', svgPath, '--output', 'temp.svg', '--quiet']); - const optimizedFileLength = fs.readFileSync('temp.svg').length; - expect(optimizedFileLength).toBeLessThanOrEqual(initialFileLength); - await del('temp.svg'); - }); - it('should optimize several files', async () => { const initWeight = calcFolderSvgWeight(svgFolderPath); await runProgram([ @@ -148,29 +108,6 @@ describe('coa', function () { await del('temp.svg'); }); - it('should optimize file from process.stdin', async () => { - const initialFile = fs.readFileSync(path.resolve(__dirname, 'test.svg')); - const stdin = require('mock-stdin').stdin(); - setTimeout(() => { - stdin.send(initialFile, 'ascii').end(); - }, 1000); - try { - await runProgram([ - '--input', - '-', - '--output', - 'temp.svg', - '--string', - fs.readFileSync(svgPath, 'utf8'), - '--quiet', - ]); - } finally { - const optimizedFileLength = fs.readFileSync('temp.svg').length; - expect(optimizedFileLength).toBeLessThanOrEqual(initialFile.length); - await del('temp.svg'); - } - }); - it('should optimize folder, when it stated in input', async () => { const initWeight = calcFolderSvgWeight(svgFolderPath); await runProgram([ @@ -200,23 +137,6 @@ describe('coa', function () { }); describe('stdout', () => { - it('should show file content when no output set', async () => { - replaceConsoleLog(); - try { - await runProgram([ - '--string', - fs.readFileSync(svgPath, 'utf8'), - '--output', - '-', - '--datauri', - 'unenc', - ]); - } finally { - restoreConsoleLog(); - expect(output).toMatch(/www\.w3\.org\/2000\/svg/); - } - }); - it('should show message when the folder is empty', async () => { const emptyFolderPath = path.resolve(__dirname, 'testSvgEmpty'); if (!fs.existsSync(emptyFolderPath)) { @@ -240,15 +160,5 @@ describe('coa', function () { expect(error.message).toMatch(/No SVG files have been found/); } }); - - it('should show plugins', async () => { - replaceConsoleLog(); - try { - await runProgram(['--show-plugins']); - } finally { - restoreConsoleLog(); - expect(output).toMatch(/Currently available plugins:/); - } - }); }); }); diff --git a/test/coa/test.svg b/test/coa/test.svg deleted file mode 100644 index de7975de7..000000000 --- a/test/coa/test.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9ba410f99..97807c29e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3790,13 +3790,6 @@ __metadata: languageName: node linkType: hard -"mock-stdin@npm:^1.0.0": - version: 1.0.0 - resolution: "mock-stdin@npm:1.0.0" - checksum: 34d2affa0607813130118a62540c33c0d121f9d5bcdbaf1e2dde3dc91eb899b0e803221a591acdc4950b85271f5c04994efcead3631e63f19d04b4fb3d1e2da4 - languageName: node - linkType: hard - "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -4829,7 +4822,6 @@ __metadata: del: ^6.0.0 eslint: ^7.32.0 jest: ^27.2.5 - mock-stdin: ^1.0.0 node-fetch: ^2.6.2 picocolors: ^1.0.0 pixelmatch: ^5.2.1