2021-02-19 04:31:33 +00:00
import { promises as fs } from 'fs'
import { tmpdir } from 'os'
import { join , resolve } from 'path'
2020-12-13 00:18:25 +00:00
2021-06-05 15:29:15 +00:00
import packwatch from '../src'
2023-03-22 03:53:06 +00:00
import type { Report } from '../src/types'
2021-06-05 15:29:15 +00:00
let workspace : string | null
2020-12-13 00:18:25 +00:00
2021-02-19 04:31:33 +00:00
async function prepareWorkspace ( ) : Promise < string > {
2021-03-19 20:49:27 +00:00
const workspacePath = await fs . mkdtemp ( ` ${ tmpdir ( ) } / ` )
2021-06-05 15:29:15 +00:00
workspace = workspacePath
2021-02-19 04:31:33 +00:00
return workspacePath
2020-12-13 00:18:25 +00:00
}
2021-02-19 04:31:33 +00:00
async function cleanUpWorkspace ( paths : string [ ] ) : Promise < void > {
2021-03-19 20:49:27 +00:00
await Promise . all (
2021-06-05 16:21:47 +00:00
paths . map ( async ( path ) = > fs . rmdir ( path , { recursive : true } ) ) ,
2021-02-19 04:31:33 +00:00
)
2020-12-13 00:18:25 +00:00
}
2021-02-19 04:31:33 +00:00
async function createFile ( path : string , content : string ) : Promise < void > {
await fs . writeFile ( path , content )
}
async function createPackageJson ( cwd : string ) : Promise < void > {
const path = resolve ( join ( cwd , 'package.json' ) )
await createFile (
path ,
'{ "name": "wow", "version": "0.0.0", "files": ["!.packwatch.json"] }' ,
)
}
async function createManifest (
cwd : string ,
configuration : Report ,
) : Promise < void > {
const path = resolve ( join ( cwd , '.packwatch.json' ) )
await createFile ( path , JSON . stringify ( configuration ) )
2020-12-13 00:18:25 +00:00
}
2021-06-05 15:29:15 +00:00
describe ( 'Packwatch' , ( ) = > {
2021-02-19 04:31:33 +00:00
afterEach ( async ( ) = > {
jest . restoreAllMocks ( )
2020-12-13 00:18:25 +00:00
2021-06-05 15:29:15 +00:00
if ( workspace ) {
await cleanUpWorkspace ( [ workspace ] )
workspace = null
2021-02-19 04:31:33 +00:00
}
} )
2020-12-13 00:18:25 +00:00
2021-02-19 04:31:33 +00:00
it ( 'warns the user and errors if run away from package.json' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockLogger = jest . spyOn ( console , 'log' )
2021-03-19 20:49:27 +00:00
await expect ( async ( ) = >
packwatch ( { cwd : workspacePath } ) ,
) . rejects . toThrow ( 'NOT_IN_PACKAGE_ROOT' )
2020-12-13 00:18:25 +00:00
expect ( mockLogger . mock . calls ) . toHaveLength ( 1 )
2021-02-19 04:31:33 +00:00
expect ( mockLogger . mock . calls [ 0 ] [ 0 ] ) . toEqual (
expect . stringMatching (
'There is no package.json file here. Are you in the root directory of your project?' ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
describe ( 'without manifest' , ( ) = > {
2021-02-19 04:31:33 +00:00
it ( 'generates the initial manifest properly' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
2020-12-13 00:18:25 +00:00
2021-03-19 20:49:27 +00:00
await expect ( async ( ) = >
packwatch ( { cwd : workspacePath } ) ,
) . rejects . toThrow ( 'NO_MANIFEST_NO_UPDATE' )
2020-12-13 00:18:25 +00:00
2021-02-19 04:31:33 +00:00
const generatedManifest = await fs . readFile (
resolve ( join ( workspacePath , '.packwatch.json' ) ) ,
{ encoding : 'utf8' } ,
)
2023-03-22 03:53:06 +00:00
expect ( generatedManifest ) . toBe (
2021-02-19 04:31:33 +00:00
'{"limit":"160 B","packageSize":"160 B","unpackedSize":"68 B"}' ,
)
} )
it ( 'outputs expected messaging' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockWarn = jest . spyOn ( console , 'warn' )
const mockError = jest . spyOn ( console , 'error' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
2020-12-13 00:18:25 +00:00
2021-03-19 20:49:27 +00:00
await expect ( async ( ) = >
packwatch ( { cwd : workspacePath } ) ,
) . rejects . toThrow ( )
2020-12-13 00:18:25 +00:00
2021-03-19 20:49:27 +00:00
expect ( mockWarn . mock . calls ) . toHaveLength ( 1 )
expect ( mockWarn . mock . calls [ 0 ] [ 0 ] ) . toEqual (
2021-02-19 04:31:33 +00:00
expect . stringMatching (
/No Manifest to compare against! Current package stats written to \.packwatch\.json!\nPackage size \(\d+ B\) adopted as new limit\./ ,
) ,
)
2021-03-19 20:49:27 +00:00
expect ( mockError . mock . calls ) . toHaveLength ( 1 )
expect ( mockError . mock . calls [ 0 ] [ 0 ] ) . toEqual (
2021-02-19 04:31:33 +00:00
expect . stringMatching (
'It looks like you ran PackWatch without a manifest. To prevent accidental passes in CI or hooks, packwatch will terminate with an error. If you are running packwatch for the first time in your project, this is expected!' ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
2021-02-19 04:31:33 +00:00
it ( 'outputs expected messaging when not updating the manifest' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const mockWarn = jest . spyOn ( console , 'warn' )
const workspacePath = await prepareWorkspace ( )
2020-12-13 00:18:25 +00:00
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
2021-03-19 20:49:27 +00:00
await packwatch ( { cwd : workspacePath , isUpdatingManifest : true } )
2020-12-13 00:18:25 +00:00
2021-03-19 20:49:27 +00:00
expect ( mockWarn . mock . calls ) . toHaveLength ( 1 )
expect ( mockWarn . mock . calls [ 0 ] [ 0 ] ) . toEqual (
2021-02-19 04:31:33 +00:00
expect . stringMatching (
/No Manifest to compare against! Current package stats written to \.packwatch\.json!\nPackage size \(\d+ B\) adopted as new limit\./ ,
) ,
)
2020-12-13 00:18:25 +00:00
} )
} )
describe ( 'with manifest' , ( ) = > {
2021-02-19 04:31:33 +00:00
it ( 'messages when the size is equal to the limit' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockLogger = jest . spyOn ( console , 'log' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
await createManifest ( workspacePath , {
limit : '160B' ,
packageSize : '160B' ,
2021-06-05 15:29:15 +00:00
packageSizeBytes : 160 ,
2021-02-19 04:31:33 +00:00
unpackedSize : '150B' ,
2021-06-05 15:29:15 +00:00
unpackedSizeBytes : 150 ,
2020-12-13 00:18:25 +00:00
} )
2021-03-19 20:49:27 +00:00
await packwatch ( { cwd : workspacePath } )
2020-12-13 00:18:25 +00:00
expect ( mockLogger . mock . calls ) . toHaveLength ( 1 )
2021-02-19 04:31:33 +00:00
expect ( mockLogger . mock . calls [ 0 ] [ 0 ] ) . toEqual (
expect . stringMatching (
/Nothing to report! Your package is the same size as the latest manifest reports! \(Limit: 160B\)/ ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
2021-02-19 04:31:33 +00:00
it ( 'messages when the size is lower than the limit (no growth)' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockLogger = jest . spyOn ( console , 'log' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
await createManifest ( workspacePath , {
limit : '170B' ,
packageSize : '160B' ,
2021-06-05 15:29:15 +00:00
packageSizeBytes : 160 ,
2021-02-19 04:31:33 +00:00
unpackedSize : '150B' ,
2021-06-05 15:29:15 +00:00
unpackedSizeBytes : 150 ,
2020-12-13 00:18:25 +00:00
} )
2021-02-19 04:31:33 +00:00
2021-03-19 20:49:27 +00:00
await packwatch ( { cwd : workspacePath } )
2020-12-13 00:18:25 +00:00
expect ( mockLogger . mock . calls ) . toHaveLength ( 1 )
2021-02-19 04:31:33 +00:00
expect ( mockLogger . mock . calls [ 0 ] [ 0 ] ) . toEqual (
expect . stringMatching (
/Nothing to report! Your package is the same size as the latest manifest reports! \(Limit: 170B\)/ ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
2021-02-19 04:31:33 +00:00
it ( 'messages when the size is lower than the limit (growth)' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockLogger = jest . spyOn ( console , 'log' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
await createManifest ( workspacePath , {
limit : '180B' ,
packageSize : '150B' ,
2021-06-05 15:29:15 +00:00
packageSizeBytes : 150 ,
2021-02-19 04:31:33 +00:00
unpackedSize : '140B' ,
2021-06-05 15:29:15 +00:00
unpackedSizeBytes : 140 ,
2020-12-13 00:18:25 +00:00
} )
2021-02-19 04:31:33 +00:00
2021-03-19 20:49:27 +00:00
await packwatch ( { cwd : workspacePath } )
2020-12-13 00:18:25 +00:00
expect ( mockLogger . mock . calls ) . toHaveLength ( 1 )
2021-02-19 04:31:33 +00:00
expect ( mockLogger . mock . calls [ 0 ] [ 0 ] ) . toEqual (
expect . stringMatching (
/Your package grew! \d+ B > 150B \(Limit: 180B\)/ ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
2021-02-19 04:31:33 +00:00
it ( 'messages when the size is lower than the limit (shrinkage)' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockLogger = jest . spyOn ( console , 'log' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
await createManifest ( workspacePath , {
limit : '180B' ,
packageSize : '170B' ,
2021-06-05 15:29:15 +00:00
packageSizeBytes : 170 ,
2021-02-19 04:31:33 +00:00
unpackedSize : '140B' ,
2021-06-05 15:29:15 +00:00
unpackedSizeBytes : 140 ,
2020-12-13 00:18:25 +00:00
} )
2021-02-19 04:31:33 +00:00
2021-03-19 20:49:27 +00:00
await packwatch ( { cwd : workspacePath } )
2020-12-13 00:18:25 +00:00
expect ( mockLogger . mock . calls ) . toHaveLength ( 1 )
2021-02-19 04:31:33 +00:00
expect ( mockLogger . mock . calls [ 0 ] [ 0 ] ) . toEqual (
expect . stringMatching (
/Your package shrank! \d+ B < 170B \(Limit: 180B\)/ ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
2021-02-19 04:31:33 +00:00
it ( 'messages when the size exceeds the limit' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockError = jest . spyOn ( console , 'error' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
await createManifest ( workspacePath , {
limit : '10B' ,
packageSize : '170B' ,
2021-06-05 15:29:15 +00:00
packageSizeBytes : 170 ,
2021-02-19 04:31:33 +00:00
unpackedSize : '140B' ,
2021-06-05 15:29:15 +00:00
unpackedSizeBytes : 140 ,
2020-12-13 00:18:25 +00:00
} )
2021-02-19 04:31:33 +00:00
2021-03-19 20:49:27 +00:00
await expect ( async ( ) = >
packwatch ( { cwd : workspacePath } ) ,
) . rejects . toThrow ( 'PACKAGE_EXCEEDS_LIMIT' )
expect ( mockError . mock . calls ) . toHaveLength ( 1 )
expect ( mockError . mock . calls [ 0 ] [ 0 ] ) . toEqual (
2021-02-19 04:31:33 +00:00
expect . stringMatching (
/Your package exceeds the limit set in \.packwatch\.json! \d+ B > 10B\nEither update the limit by using the --update-manifest flag or trim down your packed files!/ ,
) ,
)
2020-12-13 00:18:25 +00:00
} )
2021-02-19 04:31:33 +00:00
it ( 'messages when updating the manifest' , async ( ) = > {
2021-06-05 15:29:15 +00:00
const workspacePath = await prepareWorkspace ( )
const mockLogger = jest . spyOn ( console , 'log' )
2021-02-19 04:31:33 +00:00
await createPackageJson ( workspacePath )
await createManifest ( workspacePath , {
limit : '10B' ,
packageSize : '170B' ,
2021-06-05 15:29:15 +00:00
packageSizeBytes : 170 ,
2021-02-19 04:31:33 +00:00
unpackedSize : '140B' ,
2021-06-05 15:29:15 +00:00
unpackedSizeBytes : 140 ,
2020-12-13 00:18:25 +00:00
} )
2021-02-19 04:31:33 +00:00
2021-03-19 20:49:27 +00:00
await packwatch ( { cwd : workspacePath , isUpdatingManifest : true } )
2020-12-13 00:18:25 +00:00
expect ( mockLogger . mock . calls ) . toHaveLength ( 1 )
2021-02-19 04:31:33 +00:00
expect ( mockLogger . mock . calls [ 0 ] [ 0 ] ) . toEqual (
expect . stringMatching (
/Updated the manifest! Package size: \d+ B, Limit: \d+ B/ ,
) ,
2020-12-13 00:18:25 +00:00
)
} )
} )
} )