@@ -13,6 +13,7 @@ const path = require('path');
1313const fs = require ( 'fs' ) ;
1414const chai = require ( 'chai' ) ;
1515const expect = chai . expect ;
16+ const regexEscaper = require ( '../../lib/utils/regexp-escaper' ) ;
1617
1718const loadManifest = function ( webpackConfig ) {
1819 return JSON . parse (
@@ -30,6 +31,27 @@ const readOutputFile = function(webpackConfig, filePath) {
3031 return fs . readFileSync ( fullPath , 'utf8' ) ;
3132} ;
3233
34+ /**
35+ * Returns a regex to use to match this filename
36+ *
37+ * @param {string } filename Filename with possible [hash:8] wildcard
38+ * @return {RegExp }
39+ */
40+ const convertFilenameToMatcher = function ( filename ) {
41+ const hashMatch = filename . match ( / \[ h a s h : ( \d + ) \] / ) ;
42+
43+ if ( hashMatch === null ) {
44+ return new RegExp ( regexEscaper ( filename ) ) ;
45+ }
46+
47+ const [ hashString , hashLength ] = hashMatch ;
48+
49+ return new RegExp (
50+ regexEscaper ( filename )
51+ . replace ( regexEscaper ( hashString ) , `([a-z0-9_-]){${ hashLength } }` )
52+ ) ;
53+ } ;
54+
3355class Assert {
3456 /**
3557 * @param {WebpackConfig } webpackConfig
@@ -107,8 +129,10 @@ class Assert {
107129
108130 this . assertManifestKeyExists ( sourcePath ) ;
109131
110- if ( manifestData [ sourcePath ] !== expectedDestinationPath ) {
111- throw new Error ( `source path ${ sourcePath } expected to be set to ${ expectedDestinationPath } , was actually ${ manifestData [ sourcePath ] } ` ) ;
132+ const expectedRegex = convertFilenameToMatcher ( expectedDestinationPath ) ;
133+
134+ if ( ! manifestData [ sourcePath ] . match ( expectedRegex ) ) {
135+ throw new Error ( `source path ${ sourcePath } expected to match pattern ${ expectedDestinationPath } , was actually ${ manifestData [ sourcePath ] } ` ) ;
112136 }
113137 }
114138
@@ -168,6 +192,57 @@ class Assert {
168192
169193 expect ( JSON . stringify ( actualData , null , 2 ) ) . to . equal ( JSON . stringify ( expectedData , null , 2 ) ) ;
170194 }
195+
196+ /**
197+ * Verifies that the directory contains the array of files.
198+ *
199+ * The expectedFiles can contain a [hash:8] syntax in case
200+ * the file is versioned - e.g. main.[hash:8].js, which would
201+ * match a real file like main.abcd1234.js.
202+ *
203+ * @param {Array } expectedFiles
204+ * @param {string } directory relative to output to check
205+ * @returns {void }
206+ */
207+ assertDirectoryContents ( expectedFiles , directory = '' ) {
208+ const targetDirectory = path . join ( this . webpackConfig . outputPath , directory ) ;
209+
210+ expect ( targetDirectory ) . to . be . a . directory ( ) ;
211+
212+ const expectedFileStrings = { } ;
213+ expectedFiles . forEach ( ( expectedFile ) => {
214+ expectedFileStrings [ expectedFile ] = convertFilenameToMatcher ( expectedFile ) ;
215+ } ) ;
216+
217+ const actualFiles = fs . readdirSync ( targetDirectory ) ;
218+ actualFiles . forEach ( ( foundFile ) => {
219+ // filter out directories
220+ if ( fs . statSync ( path . join ( targetDirectory , foundFile ) ) . isDirectory ( ) ) {
221+ return ;
222+ }
223+
224+ let matchIsFound = false ;
225+
226+ for ( const originalFilename of Object . keys ( expectedFileStrings ) ) {
227+ const filenameRegex = expectedFileStrings [ originalFilename ] ;
228+
229+ if ( foundFile . match ( filenameRegex ) ) {
230+ matchIsFound = true ;
231+ delete expectedFileStrings [ originalFilename ] ;
232+
233+ break ;
234+ }
235+ }
236+
237+ if ( ! matchIsFound ) {
238+ throw new Error ( `File "${ foundFile } " was found in directory but was not expected. Expected patterns where ${ expectedFiles . join ( ', ' ) } ` ) ;
239+ }
240+ } ) ;
241+
242+ if ( Object . keys ( expectedFileStrings ) . length > 0 ) {
243+ throw new Error ( `Files ${ Object . keys ( expectedFileStrings ) . join ( ', ' ) } were expected to be found in the directory but were not. Actual files: ${ actualFiles . join ( ', ' ) } ` ) ;
244+ }
245+ }
171246}
172247
173248module . exports = function ( webpackConfig ) {
0 commit comments