mirror of
				https://github.com/theoludwig/html-w3c-validator.git
				synced 2025-05-21 23:21:29 +02:00 
			
		
		
		
	test: add automated tests
This commit is contained in:
		
							
								
								
									
										3
									
								
								.html-w3c-validatorrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.html-w3c-validatorrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|   "files": ["./example/build/index.html", "./example/build/about.html"] | ||||
| } | ||||
							
								
								
									
										1
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| fixtures | ||||
							
								
								
									
										2
									
								
								example/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								example/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -36,6 +36,7 @@ | ||||
|         "@types/html-validator": "5.0.3", | ||||
|         "@types/mock-fs": "4.13.1", | ||||
|         "@types/node": "20.4.9", | ||||
|         "@types/sinon": "10.0.16", | ||||
|         "@typescript-eslint/eslint-plugin": "6.3.0", | ||||
|         "@typescript-eslint/parser": "6.3.0", | ||||
|         "editorconfig-checker": "5.1.1", | ||||
| @@ -55,6 +56,7 @@ | ||||
|         "rimraf": "5.0.1", | ||||
|         "semantic-release": "21.0.7", | ||||
|         "serve": "14.2.0", | ||||
|         "sinon": "15.2.0", | ||||
|         "typescript": "5.1.6" | ||||
|       }, | ||||
|       "engines": { | ||||
|   | ||||
							
								
								
									
										146
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										146
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -29,6 +29,7 @@ | ||||
|         "@types/html-validator": "5.0.3", | ||||
|         "@types/mock-fs": "4.13.1", | ||||
|         "@types/node": "20.4.9", | ||||
|         "@types/sinon": "10.0.16", | ||||
|         "@typescript-eslint/eslint-plugin": "6.3.0", | ||||
|         "@typescript-eslint/parser": "6.3.0", | ||||
|         "editorconfig-checker": "5.1.1", | ||||
| @@ -48,6 +49,7 @@ | ||||
|         "rimraf": "5.0.1", | ||||
|         "semantic-release": "21.0.7", | ||||
|         "serve": "14.2.0", | ||||
|         "sinon": "15.2.0", | ||||
|         "typescript": "5.1.6" | ||||
|       }, | ||||
|       "engines": { | ||||
| @@ -1693,6 +1695,50 @@ | ||||
|         "url": "https://github.com/sindresorhus/is?sponsor=1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@sinonjs/commons": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", | ||||
|       "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "type-detect": "4.0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@sinonjs/fake-timers": { | ||||
|       "version": "10.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", | ||||
|       "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@sinonjs/commons": "^3.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@sinonjs/samsam": { | ||||
|       "version": "8.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", | ||||
|       "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@sinonjs/commons": "^2.0.0", | ||||
|         "lodash.get": "^4.4.2", | ||||
|         "type-detect": "^4.0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", | ||||
|       "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "type-detect": "4.0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@sinonjs/text-encoding": { | ||||
|       "version": "0.7.2", | ||||
|       "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", | ||||
|       "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/@swc/cli": { | ||||
|       "version": "0.1.62", | ||||
|       "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.1.62.tgz", | ||||
| @@ -2031,6 +2077,21 @@ | ||||
|       "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/@types/sinon": { | ||||
|       "version": "10.0.16", | ||||
|       "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.16.tgz", | ||||
|       "integrity": "sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@types/sinonjs__fake-timers": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/sinonjs__fake-timers": { | ||||
|       "version": "8.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", | ||||
|       "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/@typescript-eslint/eslint-plugin": { | ||||
|       "version": "6.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", | ||||
| @@ -4080,6 +4141,15 @@ | ||||
|       "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/diff": { | ||||
|       "version": "5.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", | ||||
|       "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", | ||||
|       "dev": true, | ||||
|       "engines": { | ||||
|         "node": ">=0.3.1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dir-glob": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", | ||||
| @@ -6523,6 +6593,12 @@ | ||||
|         "node": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/just-extend": { | ||||
|       "version": "4.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", | ||||
|       "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/keyv": { | ||||
|       "version": "4.5.3", | ||||
|       "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", | ||||
| @@ -6838,6 +6914,12 @@ | ||||
|       "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/lodash.get": { | ||||
|       "version": "4.4.2", | ||||
|       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", | ||||
|       "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/lodash.isfunction": { | ||||
|       "version": "3.0.9", | ||||
|       "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", | ||||
| @@ -7489,6 +7571,43 @@ | ||||
|       "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/nise": { | ||||
|       "version": "5.1.4", | ||||
|       "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", | ||||
|       "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@sinonjs/commons": "^2.0.0", | ||||
|         "@sinonjs/fake-timers": "^10.0.2", | ||||
|         "@sinonjs/text-encoding": "^0.7.1", | ||||
|         "just-extend": "^4.0.2", | ||||
|         "path-to-regexp": "^1.7.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/nise/node_modules/@sinonjs/commons": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", | ||||
|       "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "type-detect": "4.0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/nise/node_modules/isarray": { | ||||
|       "version": "0.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", | ||||
|       "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/nise/node_modules/path-to-regexp": { | ||||
|       "version": "1.8.0", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", | ||||
|       "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "isarray": "0.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/node-emoji": { | ||||
|       "version": "1.11.0", | ||||
|       "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", | ||||
| @@ -12781,6 +12900,24 @@ | ||||
|         "node": ">=4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/sinon": { | ||||
|       "version": "15.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.2.0.tgz", | ||||
|       "integrity": "sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@sinonjs/commons": "^3.0.0", | ||||
|         "@sinonjs/fake-timers": "^10.3.0", | ||||
|         "@sinonjs/samsam": "^8.0.0", | ||||
|         "diff": "^5.1.0", | ||||
|         "nise": "^5.1.4", | ||||
|         "supports-color": "^7.2.0" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "type": "opencollective", | ||||
|         "url": "https://opencollective.com/sinon" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/sisteransi": { | ||||
|       "version": "1.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", | ||||
| @@ -13539,6 +13676,15 @@ | ||||
|         "node": ">= 0.8.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/type-detect": { | ||||
|       "version": "4.0.8", | ||||
|       "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", | ||||
|       "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", | ||||
|       "dev": true, | ||||
|       "engines": { | ||||
|         "node": ">=4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/type-fest": { | ||||
|       "version": "0.20.2", | ||||
|       "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", | ||||
|   | ||||
| @@ -66,6 +66,7 @@ | ||||
|     "@types/html-validator": "5.0.3", | ||||
|     "@types/mock-fs": "4.13.1", | ||||
|     "@types/node": "20.4.9", | ||||
|     "@types/sinon": "10.0.16", | ||||
|     "@typescript-eslint/eslint-plugin": "6.3.0", | ||||
|     "@typescript-eslint/parser": "6.3.0", | ||||
|     "editorconfig-checker": "5.1.1", | ||||
| @@ -85,6 +86,7 @@ | ||||
|     "rimraf": "5.0.1", | ||||
|     "semantic-release": "21.0.7", | ||||
|     "serve": "14.2.0", | ||||
|     "sinon": "15.2.0", | ||||
|     "typescript": "5.1.6" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -17,9 +17,9 @@ import { isExistingPath } from './utils/isExistingPath.js' | ||||
|  | ||||
| export const CONFIG_FILE_NAME = '.html-w3c-validatorrc.json' | ||||
|  | ||||
| const severities = ['error', 'warning', 'info'] as const | ||||
| export const SEVERITIES = ['error', 'warning', 'info'] as const | ||||
|  | ||||
| export type Severity = (typeof severities)[number] | ||||
| export type Severity = (typeof SEVERITIES)[number] | ||||
|  | ||||
| interface Config { | ||||
|   urls?: string[] | ||||
| @@ -113,22 +113,19 @@ export class HTMLValidatorCommand extends Command { | ||||
|           `Invalid config file at "${configPath}". Please add URLs or files.` | ||||
|         ) | ||||
|       } | ||||
|       const configSeverities: Severity[] = config.severities ?? [ | ||||
|         'warning', | ||||
|         'error' | ||||
|       ] | ||||
|       for (const severity of configSeverities) { | ||||
|         if (!severities.includes(severity)) { | ||||
|       const severities: Severity[] = config.severities ?? ['warning', 'error'] | ||||
|       for (const severity of severities) { | ||||
|         if (!SEVERITIES.includes(severity)) { | ||||
|           throw new Error( | ||||
|             `Invalid config file at "${configPath}". Please add valid severities (${severities.join( | ||||
|             `Invalid config file at "${configPath}". Please add valid severities (${SEVERITIES.join( | ||||
|               ', ' | ||||
|             )}).` | ||||
|           ) | ||||
|         } | ||||
|       } | ||||
|       if (configSeverities.length === 0) { | ||||
|       if (severities.length === 0) { | ||||
|         throw new Error( | ||||
|           `Invalid config file at "${configPath}". Please add valid severities (${severities.join( | ||||
|           `Invalid config file at "${configPath}". Please add valid severities (${SEVERITIES.join( | ||||
|             ', ' | ||||
|           )}).` | ||||
|         ) | ||||
| @@ -169,8 +166,8 @@ export class HTMLValidatorCommand extends Command { | ||||
|             } | ||||
|             const hasErrors = result.messages.some((message) => { | ||||
|               return ( | ||||
|                 configSeverities.includes(message.type as Severity) || | ||||
|                 configSeverities.includes(message.subType as Severity) | ||||
|                 severities.includes(message.type as Severity) || | ||||
|                 severities.includes(message.subType as Severity) | ||||
|               ) | ||||
|             }) | ||||
|             if (!hasErrors) { | ||||
|   | ||||
| @@ -1,23 +1,377 @@ | ||||
| import test from 'node:test' | ||||
| import assert from 'node:assert/strict' | ||||
| import path from 'node:path' | ||||
| import { PassThrough } from 'node:stream' | ||||
|  | ||||
| import sinon from 'sinon' | ||||
| import { execa } from 'execa' | ||||
| import { table } from 'table' | ||||
| import chalk from 'chalk' | ||||
| import logSymbols from 'log-symbols' | ||||
|  | ||||
| import { cli } from '../cli.js' | ||||
| import { HTMLValidatorCommand } from '../HTMLValidatorCommand.js' | ||||
| import { | ||||
|   HTMLValidatorCommand, | ||||
|   CONFIG_FILE_NAME, | ||||
|   SEVERITIES | ||||
| } from '../HTMLValidatorCommand.js' | ||||
|  | ||||
| const FIXTURES_PATH = path.join(process.cwd(), 'src', '__test__', 'fixtures') | ||||
|  | ||||
| await test('html-w3c-validator', async (t) => { | ||||
|   t.afterEach(() => { | ||||
|     sinon.restore() | ||||
|   }) | ||||
|  | ||||
|   await t.test('should be instance of the command', async () => { | ||||
|     const command = cli.process([]) | ||||
|     assert(command instanceof HTMLValidatorCommand) | ||||
|   }) | ||||
|  | ||||
|   await t.test('succeeds and validate the html correctly', async () => { | ||||
|     const exampleURL = new URL('../../example', import.meta.url) | ||||
|     process.chdir(exampleURL.pathname) | ||||
|     await execa('rimraf', ['node_modules']) | ||||
|     await execa('npm', ['install']) | ||||
|     const { exitCode } = await execa('npm', ['run', 'test:html-w3c-validator']) | ||||
|     assert.strictEqual(exitCode, 0) | ||||
|   await t.test( | ||||
|     'succeeds and validate the html correctly (example)', | ||||
|     async () => { | ||||
|       const exampleURL = new URL('../../example', import.meta.url) | ||||
|       process.chdir(exampleURL.pathname) | ||||
|       await execa('rimraf', ['node_modules']) | ||||
|       await execa('npm', ['install']) | ||||
|       const { exitCode } = await execa('npm', [ | ||||
|         'run', | ||||
|         'test:html-w3c-validator' | ||||
|       ]) | ||||
|       assert.strictEqual(exitCode, 0) | ||||
|     } | ||||
|   ) | ||||
|  | ||||
|   await t.test( | ||||
|     'succeeds and validate the html correctly (example without working directory)', | ||||
|     async () => { | ||||
|       const logs: string[] = [] | ||||
|       sinon.stub(console, 'log').value((log: string) => { | ||||
|         logs.push(log) | ||||
|       }) | ||||
|       const consoleLogSpy = sinon.spy(console, 'log') | ||||
|       const stream = new PassThrough() | ||||
|       const exitCode = await cli.run([], { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       }) | ||||
|       stream.end() | ||||
|       assert.strictEqual(exitCode, 0) | ||||
|       assert.strictEqual( | ||||
|         consoleLogSpy.calledWith( | ||||
|           logSymbols.success, | ||||
|           './example/build/index.html' | ||||
|         ), | ||||
|         true, | ||||
|         logs.join('\n') | ||||
|       ) | ||||
|       assert.strictEqual( | ||||
|         consoleLogSpy.calledWith( | ||||
|           logSymbols.success, | ||||
|           './example/build/about.html' | ||||
|         ), | ||||
|         true, | ||||
|         logs.join('\n') | ||||
|       ) | ||||
|     } | ||||
|   ) | ||||
|  | ||||
|   await t.test( | ||||
|     'succeeds and validate the html correctly (fixture)', | ||||
|     async () => { | ||||
|       const workingDirectory = path.join(FIXTURES_PATH, 'success') | ||||
|       const logs: string[] = [] | ||||
|       sinon.stub(console, 'log').value((log: string) => { | ||||
|         logs.push(log) | ||||
|       }) | ||||
|       const consoleLogSpy = sinon.spy(console, 'log') | ||||
|       const stream = new PassThrough() | ||||
|       const exitCode = await cli.run( | ||||
|         [`--current-working-directory=${workingDirectory}`], | ||||
|         { | ||||
|           stdin: process.stdin, | ||||
|           stdout: stream, | ||||
|           stderr: stream | ||||
|         } | ||||
|       ) | ||||
|       stream.end() | ||||
|       assert.strictEqual(exitCode, 0) | ||||
|       assert.strictEqual( | ||||
|         consoleLogSpy.calledWith(logSymbols.success, './build/index.html'), | ||||
|         true, | ||||
|         logs.join('\n') | ||||
|       ) | ||||
|       assert.strictEqual( | ||||
|         consoleLogSpy.calledWith(logSymbols.success, './build/about.html'), | ||||
|         true, | ||||
|         logs.join('\n') | ||||
|       ) | ||||
|     } | ||||
|   ) | ||||
|  | ||||
|   await t.test('fails with not found config', async () => { | ||||
|     const workingDirectory = path.join(FIXTURES_PATH, 'error-config-not-found') | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` No config file found at ${configPath}. Please create "${CONFIG_FILE_NAME}".` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid JSON config', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-config-invalid-json' | ||||
|     ) | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` Invalid config file at "${configPath}". Please check the JSON syntax.` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid URLs config', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-config-invalid-urls' | ||||
|     ) | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` Invalid config file at "${configPath}". Please include an array of URLs.` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid files config', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-config-invalid-files' | ||||
|     ) | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` Invalid config file at "${configPath}". Please include an array of files.` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid files and urls config', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-config-invalid-files-and-urls' | ||||
|     ) | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` Invalid config file at "${configPath}". Please add URLs or files.` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid severities config', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-config-invalid-severities' | ||||
|     ) | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` Invalid config file at "${configPath}". Please add valid severities (${SEVERITIES.join( | ||||
|             ', ' | ||||
|           )}).` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid empty severities config', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-config-invalid-severities-empty' | ||||
|     ) | ||||
|     const configPath = path.join(workingDirectory, CONFIG_FILE_NAME) | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + | ||||
|           ` Invalid config file at "${configPath}". Please add valid severities (${SEVERITIES.join( | ||||
|             ', ' | ||||
|           )}).` | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
|  | ||||
|   await t.test('fails with invalid files paths to check', async () => { | ||||
|     const workingDirectory = path.join( | ||||
|       FIXTURES_PATH, | ||||
|       'error-invalid-files-paths-to-check' | ||||
|     ) | ||||
|     const htmlPath = path.resolve(workingDirectory, 'index.html') | ||||
|     const errors: string[] = [] | ||||
|     sinon.stub(console, 'error').value((error: string) => { | ||||
|       errors.push(error) | ||||
|     }) | ||||
|     const consoleErrorSpy = sinon.spy(console, 'error') | ||||
|     const stream = new PassThrough() | ||||
|     const exitCode = await cli.run( | ||||
|       [`--current-working-directory=${workingDirectory}`], | ||||
|       { | ||||
|         stdin: process.stdin, | ||||
|         stdout: stream, | ||||
|         stderr: stream | ||||
|       } | ||||
|     ) | ||||
|     stream.end() | ||||
|     assert.strictEqual(exitCode, 1) | ||||
|     const messagesTable = [ | ||||
|       [`No file found at "${htmlPath}". Please check the path.`] | ||||
|     ] | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith( | ||||
|         chalk.bold.red('Error:') + ' HTML validation (W3C) failed!' | ||||
|       ), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|     assert.strictEqual( | ||||
|       consoleErrorSpy.calledWith(table(messagesTable)), | ||||
|       true, | ||||
|       errors.join('\n') | ||||
|     ) | ||||
|   }) | ||||
| }) | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| { | ||||
|   "urls": [], | ||||
|   "files": [] | ||||
| } | ||||
| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|   "files": "Invalid" | ||||
| } | ||||
| @@ -0,0 +1 @@ | ||||
| Invalid JSON | ||||
| @@ -0,0 +1,4 @@ | ||||
| { | ||||
|   "files": ["./index.html"], | ||||
|   "severities": [] | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Home</title> | ||||
|   </head> | ||||
|   <body></body> | ||||
| </html> | ||||
| @@ -0,0 +1,4 @@ | ||||
| { | ||||
|   "files": ["./index.html"], | ||||
|   "severities": ["errors-invalid"] | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Home</title> | ||||
|   </head> | ||||
|   <body></body> | ||||
| </html> | ||||
| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|   "urls": "Invalid" | ||||
| } | ||||
| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|   "files": ["./index.html"] | ||||
| } | ||||
							
								
								
									
										3
									
								
								src/__test__/fixtures/success/.html-w3c-validatorrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/__test__/fixtures/success/.html-w3c-validatorrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|   "files": ["./build/index.html", "./build/about.html"] | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/__test__/fixtures/success/build/about.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/__test__/fixtures/success/build/about.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>About</title> | ||||
|   </head> | ||||
|   <body></body> | ||||
| </html> | ||||
							
								
								
									
										9
									
								
								src/__test__/fixtures/success/build/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/__test__/fixtures/success/build/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Home</title> | ||||
|   </head> | ||||
|   <body></body> | ||||
| </html> | ||||
		Reference in New Issue
	
	Block a user