build: use rome as linter+formatter #310

Merged
mcataford merged 1 commit from build/use-rome-instead-of-eslint into main 2023-03-26 15:50:28 +00:00
13 changed files with 432 additions and 2295 deletions
Showing only changes of commit d650690081 - Show all commits

View file

@ -1,13 +0,0 @@
module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
extends: [
"@tophat/eslint-config/base",
"@tophat/eslint-config/jest",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
parserOptions: {
project: ['./tsconfig.eslint.json']
}
}

View file

@ -30,8 +30,8 @@
"prepack": "yarn build", "prepack": "yarn build",
"prebuild": "rm -rf dist", "prebuild": "rm -rf dist",
"build": "tsc --project .", "build": "tsc --project .",
"lint": "eslint tests/**/*.ts src/**/*.ts", "lint": "yarn rome format src tests && yarn rome check src tests",
"lint:fix": "yarn lint --fix", "lint:fix": "yarn rome format src tests --write && yarn rome check src tests --apply",
"test": "jest tests", "test": "jest tests",
"test:watch": "yarn test --watchAll", "test:watch": "yarn test --watchAll",
"test:coverage": "yarn test --coverage", "test:coverage": "yarn test --coverage",
@ -39,19 +39,10 @@
"types:watch": "yarn types --watch" "types:watch": "yarn types --watch"
}, },
"devDependencies": { "devDependencies": {
"@tophat/eslint-config": "^6.0.1",
"@types/jest": "^29.5.0", "@types/jest": "^29.5.0",
"@types/node": "^18.15.5", "@types/node": "^18.15.5",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.8.0",
"eslint-import-resolver-node": "^0.3.7",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0", "jest": "^29.5.0",
"prettier": "^2.8.5", "rome": "^11.0.0",
"ts-jest": "^29.0.5", "ts-jest": "^29.0.5",
"typescript": "^4.3.0" "typescript": "^4.3.0"
} }

13
rome.json Normal file
View file

@ -0,0 +1,13 @@
{
"formatter": {
"enabled": true,
"lineWidth": 120
},
"javascript": {
"formatter": {
"semicolons": "asNeeded",
"quoteStyle": "single"
}
}
}

View file

@ -5,5 +5,5 @@ import packwatch from '.'
const isUpdatingManifest = process.argv.includes('--update-manifest') const isUpdatingManifest = process.argv.includes('--update-manifest')
const cwd = process.cwd() const cwd = process.cwd()
packwatch({ cwd, isUpdatingManifest }) packwatch({ cwd, isUpdatingManifest })
.catch(() => process.exit(1)) .catch(() => process.exit(1))
.then(() => process.exit(0)) .then(() => process.exit(0))

View file

@ -3,105 +3,85 @@ import { join, resolve } from 'path'
import { assertInPackageRoot } from './invariants' import { assertInPackageRoot } from './invariants'
import logger from './logger' import logger from './logger'
import { import { createOrUpdateManifest, getCurrentPackageStats, getPreviousPackageStats, mergeDefaultArguments } from './utils'
createOrUpdateManifest,
getCurrentPackageStats,
getPreviousPackageStats,
mergeDefaultArguments,
} from './utils'
import type { PackwatchArguments } from './types' import type { PackwatchArguments } from './types'
const MANIFEST_FILENAME = '.packwatch.json' const MANIFEST_FILENAME = '.packwatch.json'
export default async function packwatch( export default async function packwatch(args: Partial<PackwatchArguments>): Promise<void> {
args: Partial<PackwatchArguments>, const { cwd, isUpdatingManifest } = mergeDefaultArguments(args)
): Promise<void> {
const { cwd, isUpdatingManifest } = mergeDefaultArguments(args)
const manifestPath = resolve(join(cwd, MANIFEST_FILENAME)) const manifestPath = resolve(join(cwd, MANIFEST_FILENAME))
assertInPackageRoot(cwd) assertInPackageRoot(cwd)
const currentStats = getCurrentPackageStats(cwd) const currentStats = getCurrentPackageStats(cwd)
/* /*
* If there is no manifest file yet, we can use the current package stats as * If there is no manifest file yet, we can use the current package stats as
* a base to build one. The current package size becomes the limit. * a base to build one. The current package size becomes the limit.
*/ */
if (!existsSync(manifestPath)) { if (!existsSync(manifestPath)) {
createOrUpdateManifest({ manifestPath, current: currentStats }) createOrUpdateManifest({ manifestPath, current: currentStats })
logger.warn( logger.warn(
`📝 No Manifest to compare against! Current package stats written to ${MANIFEST_FILENAME}!\nPackage size (${currentStats.packageSize}) adopted as new limit.`, `📝 No Manifest to compare against! Current package stats written to ${MANIFEST_FILENAME}!\nPackage size (${currentStats.packageSize}) adopted as new limit.`,
) )
if (!isUpdatingManifest) { if (!isUpdatingManifest) {
logger.error( logger.error(
'❗ 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!', '❗ 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!',
) )
throw new Error('NO_MANIFEST_NO_UPDATE') throw new Error('NO_MANIFEST_NO_UPDATE')
} }
return return
} }
const previousStats = getPreviousPackageStats(cwd) const previousStats = getPreviousPackageStats(cwd)
const { packageSizeBytes, packageSize } = currentStats const { packageSizeBytes, packageSize } = currentStats
const { const { packageSize: previousSize, packageSizeBytes: previousSizeBytes, limit, limitBytes } = previousStats
packageSize: previousSize, const hasExceededLimit = limitBytes && packageSizeBytes > limitBytes
packageSizeBytes: previousSizeBytes,
limit,
limitBytes,
} = previousStats
const hasExceededLimit = limitBytes && packageSizeBytes > limitBytes
/* /*
* If we are updating the manifest, we can write right away and terminate. * If we are updating the manifest, we can write right away and terminate.
*/ */
if (isUpdatingManifest) { if (isUpdatingManifest) {
createOrUpdateManifest({ createOrUpdateManifest({
previous: previousStats, previous: previousStats,
current: currentStats, current: currentStats,
updateLimit: true, updateLimit: true,
manifestPath, manifestPath,
}) })
logger.log( logger.log(`📝 Updated the manifest! Package size: ${packageSize}, Limit: ${packageSize}`)
`📝 Updated the manifest! Package size: ${packageSize}, Limit: ${packageSize}`, return
) }
return
}
/* /*
* If there is a manifest file and the current package busts its limit * If there is a manifest file and the current package busts its limit
* we signal it and terminate with an error. * we signal it and terminate with an error.
*/ */
if (hasExceededLimit) { if (hasExceededLimit) {
logger.error( logger.error(
`🔥🔥📦🔥🔥 Your package exceeds the limit set in ${MANIFEST_FILENAME}! ${packageSize} > ${limit}\nEither update the limit by using the --update-manifest flag or trim down your packed files!`, `🔥🔥📦🔥🔥 Your package exceeds the limit set in ${MANIFEST_FILENAME}! ${packageSize} > ${limit}\nEither update the limit by using the --update-manifest flag or trim down your packed files!`,
) )
throw new Error('PACKAGE_EXCEEDS_LIMIT') throw new Error('PACKAGE_EXCEEDS_LIMIT')
} }
/* /*
* If there is a manifest file and the limit is not busted, we give * If there is a manifest file and the limit is not busted, we give
* the user some feedback on how the current package compares with * the user some feedback on how the current package compares with
* the previous one. * the previous one.
*/ */
if (packageSizeBytes > previousSizeBytes) { if (packageSizeBytes > previousSizeBytes) {
logger.log( logger.log(`📦 👀 Your package grew! ${packageSize} > ${previousSize} (Limit: ${limit})`)
`📦 👀 Your package grew! ${packageSize} > ${previousSize} (Limit: ${limit})`, } else if (packageSizeBytes < previousSizeBytes) {
) logger.log(`📦 💯 Your package shrank! ${packageSize} < ${previousSize} (Limit: ${limit})`)
} else if (packageSizeBytes < previousSizeBytes) { } else {
logger.log( logger.log(`📦 Nothing to report! Your package is the same size as the latest manifest reports! (Limit: ${limit})`)
`📦 💯 Your package shrank! ${packageSize} < ${previousSize} (Limit: ${limit})`, }
) return
} else {
logger.log(
`📦 Nothing to report! Your package is the same size as the latest manifest reports! (Limit: ${limit})`,
)
}
return
} }

View file

@ -4,13 +4,11 @@ import { join, resolve } from 'path'
import logger from './logger' import logger from './logger'
export function assertInPackageRoot(cwd: string): void { export function assertInPackageRoot(cwd: string): void {
const packagePath = resolve(join(cwd, 'package.json')) const packagePath = resolve(join(cwd, 'package.json'))
const packageJsonExists = existsSync(packagePath) const packageJsonExists = existsSync(packagePath)
if (!packageJsonExists) { if (!packageJsonExists) {
logger.log( logger.log('🤔 There is no package.json file here. Are you in the root directory of your project?')
'🤔 There is no package.json file here. Are you in the root directory of your project?', throw new Error('NOT_IN_PACKAGE_ROOT')
) }
throw new Error('NOT_IN_PACKAGE_ROOT')
}
} }

View file

@ -1,11 +1,11 @@
export default { export default {
log: (...args: unknown[]): void => { log: (...args: unknown[]): void => {
console.log(...args) console.log(...args)
}, },
warn: (...args: unknown[]): void => { warn: (...args: unknown[]): void => {
console.warn(...args) console.warn(...args)
}, },
error: (...args: unknown[]): void => { error: (...args: unknown[]): void => {
console.error(...args) console.error(...args)
}, },
} }

View file

@ -1,13 +1,13 @@
export type PackwatchArguments = { export type PackwatchArguments = {
cwd: string cwd: string
isUpdatingManifest: boolean isUpdatingManifest: boolean
} }
export type Report = { export type Report = {
packageSize: string packageSize: string
unpackedSize: string unpackedSize: string
packageSizeBytes: number packageSizeBytes: number
unpackedSizeBytes: number unpackedSizeBytes: number
limit?: string limit?: string
limitBytes?: number limitBytes?: number
} }

View file

@ -11,90 +11,88 @@ const SIZE_MAGNITUDE_PATT = /([0-9]+\.?[0-9]*)/
const MANIFEST_FILENAME = '.packwatch.json' const MANIFEST_FILENAME = '.packwatch.json'
export function mergeDefaultArguments( export function mergeDefaultArguments(args: Partial<PackwatchArguments>): PackwatchArguments {
args: Partial<PackwatchArguments>, return {
): PackwatchArguments { cwd: args.cwd ?? '.',
return { isUpdatingManifest: args.isUpdatingManifest ?? false,
cwd: args.cwd ?? '.', }
isUpdatingManifest: args.isUpdatingManifest ?? false,
}
} }
export function convertSizeToBytes(sizeString: string): number { export function convertSizeToBytes(sizeString: string): number {
const sizeSuffix = SIZE_SUFFIX_PATT.exec(sizeString)?.[1] ?? '' const sizeSuffix = SIZE_SUFFIX_PATT.exec(sizeString)?.[1] ?? ''
const sizeMagnitude = SIZE_MAGNITUDE_PATT.exec(sizeString)?.[1] ?? '0.0' const sizeMagnitude = SIZE_MAGNITUDE_PATT.exec(sizeString)?.[1] ?? '0.0'
let multiplier = 1 let multiplier = 1
if (sizeSuffix === 'kB') multiplier = 1000 if (sizeSuffix === 'kB') multiplier = 1000
else if (sizeSuffix === 'mB') { else if (sizeSuffix === 'mB') {
multiplier = 1000000 multiplier = 1000000
} }
return multiplier * parseFloat(sizeMagnitude) return multiplier * parseFloat(sizeMagnitude)
} }
export function getCurrentPackageStats(cwd: string): Report { export function getCurrentPackageStats(cwd: string): Report {
const { stderr } = spawnSync('npm', ['pack', '--dry-run'], { const { stderr } = spawnSync('npm', ['pack', '--dry-run'], {
encoding: 'utf-8', encoding: 'utf-8',
cwd, cwd,
}) })
const stderrString = String(stderr) const stderrString = String(stderr)
const packageSize = PACKAGE_SIZE_PATT.exec(stderrString)?.[1] ?? '0' const packageSize = PACKAGE_SIZE_PATT.exec(stderrString)?.[1] ?? '0'
const unpackedSize = UNPACKED_SIZE_PATT.exec(stderrString)?.[1] ?? '0' const unpackedSize = UNPACKED_SIZE_PATT.exec(stderrString)?.[1] ?? '0'
return { return {
packageSize, packageSize,
unpackedSize, unpackedSize,
packageSizeBytes: convertSizeToBytes(packageSize), packageSizeBytes: convertSizeToBytes(packageSize),
unpackedSizeBytes: convertSizeToBytes(unpackedSize), unpackedSizeBytes: convertSizeToBytes(unpackedSize),
} }
} }
export function getPreviousPackageStats(cwd: string): Report { export function getPreviousPackageStats(cwd: string): Report {
const manifestPath = resolve(join(cwd, MANIFEST_FILENAME)) const manifestPath = resolve(join(cwd, MANIFEST_FILENAME))
try { try {
const currentManifest = readFileSync(manifestPath, { const currentManifest = readFileSync(manifestPath, {
encoding: 'utf-8', encoding: 'utf-8',
}) })
const parsedManifest = JSON.parse(currentManifest) const parsedManifest = JSON.parse(currentManifest)
return { return {
...parsedManifest, ...parsedManifest,
packageSizeBytes: convertSizeToBytes(parsedManifest.packageSize), packageSizeBytes: convertSizeToBytes(parsedManifest.packageSize),
unpackedSizeBytes: convertSizeToBytes(parsedManifest.unpackedSize), unpackedSizeBytes: convertSizeToBytes(parsedManifest.unpackedSize),
limitBytes: convertSizeToBytes(parsedManifest.limit), limitBytes: convertSizeToBytes(parsedManifest.limit),
} }
} catch { } catch {
/* No manifest */ /* No manifest */
return { return {
packageSize: '0', packageSize: '0',
packageSizeBytes: 0, packageSizeBytes: 0,
unpackedSizeBytes: 0, unpackedSizeBytes: 0,
unpackedSize: '0', unpackedSize: '0',
limitBytes: 0, limitBytes: 0,
} }
} }
} }
export function createOrUpdateManifest({ export function createOrUpdateManifest({
previous, previous,
current, current,
manifestPath, manifestPath,
updateLimit = false, updateLimit = false,
}: { }: {
previous?: Report previous?: Report
current: Report current: Report
manifestPath: string manifestPath: string
updateLimit?: boolean updateLimit?: boolean
}): void { }): void {
const { limit } = previous || {} const { limit } = previous || {}
const { packageSize, unpackedSize } = current const { packageSize, unpackedSize } = current
const newManifest = { const newManifest = {
limit: updateLimit ? packageSize : limit || packageSize, limit: updateLimit ? packageSize : limit || packageSize,
packageSize: packageSize, packageSize: packageSize,
unpackedSize: unpackedSize, unpackedSize: unpackedSize,
} }
writeFileSync(manifestPath, JSON.stringify(newManifest)) writeFileSync(manifestPath, JSON.stringify(newManifest))
} }

View file

@ -9,255 +9,226 @@ import type { Report } from '../src/types'
let workspace: string | null let workspace: string | null
function getActualPackageSizeByNodeVersion(nodeVersion: string): string { function getActualPackageSizeByNodeVersion(nodeVersion: string): string {
if (nodeVersion.startsWith('v14')) return '160' if (nodeVersion.startsWith('v14')) return '160'
else if (nodeVersion.startsWith('v16')) return '157' else if (nodeVersion.startsWith('v16')) return '157'
else if (nodeVersion.startsWith('v18')) return '157' else if (nodeVersion.startsWith('v18')) return '157'
return 'unknown' return 'unknown'
} }
async function prepareWorkspace(): Promise<string> { async function prepareWorkspace(): Promise<string> {
const workspacePath = await fs.mkdtemp(`${tmpdir()}/`) const workspacePath = await fs.mkdtemp(`${tmpdir()}/`)
workspace = workspacePath workspace = workspacePath
return workspacePath return workspacePath
} }
async function cleanUpWorkspace(paths: string[]): Promise<void> { async function cleanUpWorkspace(paths: string[]): Promise<void> {
await Promise.all( await Promise.all(paths.map(async (path) => fs.rmdir(path, { recursive: true })))
paths.map(async (path) => fs.rmdir(path, { recursive: true })),
)
} }
async function createFile(path: string, content: string): Promise<void> { async function createFile(path: string, content: string): Promise<void> {
await fs.writeFile(path, content) await fs.writeFile(path, content)
} }
async function createPackageJson(cwd: string): Promise<void> { async function createPackageJson(cwd: string): Promise<void> {
const path = resolve(join(cwd, 'package.json')) const path = resolve(join(cwd, 'package.json'))
await createFile( await createFile(path, '{ "name": "wow", "version": "0.0.0", "files": ["!.packwatch.json"] }')
path,
'{ "name": "wow", "version": "0.0.0", "files": ["!.packwatch.json"] }',
)
} }
async function createManifest( async function createManifest(cwd: string, configuration: Report): Promise<void> {
cwd: string, const path = resolve(join(cwd, '.packwatch.json'))
configuration: Report, await createFile(path, JSON.stringify(configuration))
): Promise<void> {
const path = resolve(join(cwd, '.packwatch.json'))
await createFile(path, JSON.stringify(configuration))
} }
describe('Packwatch', () => { describe('Packwatch', () => {
const actualSize = getActualPackageSizeByNodeVersion(process.version) const actualSize = getActualPackageSizeByNodeVersion(process.version)
afterEach(async () => { afterEach(async () => {
jest.restoreAllMocks() jest.restoreAllMocks()
if (workspace) { if (workspace) {
await cleanUpWorkspace([workspace]) await cleanUpWorkspace([workspace])
workspace = null workspace = null
} }
}) })
it('warns the user and errors if run away from package.json', async () => { it('warns the user and errors if run away from package.json', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
const mockLogger = jest.spyOn(console, 'log') const mockLogger = jest.spyOn(console, 'log')
await expect(async () => await expect(async () => packwatch({ cwd: workspacePath })).rejects.toThrow('NOT_IN_PACKAGE_ROOT')
packwatch({ cwd: workspacePath }),
).rejects.toThrow('NOT_IN_PACKAGE_ROOT')
expect(mockLogger.mock.calls).toHaveLength(1) expect(mockLogger.mock.calls).toHaveLength(1)
expect(mockLogger.mock.calls[0][0]).toEqual( expect(mockLogger.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching('There is no package.json file here. Are you in the root directory of your project?'),
'There is no package.json file here. Are you in the root directory of your project?', )
), })
)
})
describe('without manifest', () => { describe('without manifest', () => {
it('generates the initial manifest properly', async () => { it('generates the initial manifest properly', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await expect(async () => await expect(async () => packwatch({ cwd: workspacePath })).rejects.toThrow('NO_MANIFEST_NO_UPDATE')
packwatch({ cwd: workspacePath }),
).rejects.toThrow('NO_MANIFEST_NO_UPDATE')
const generatedManifest = await fs.readFile( const generatedManifest = await fs.readFile(resolve(join(workspacePath, '.packwatch.json')), { encoding: 'utf8' })
resolve(join(workspacePath, '.packwatch.json')),
{ encoding: 'utf8' },
)
expect(generatedManifest).toBe( expect(generatedManifest).toBe(
`{"limit":"${actualSize} B","packageSize":"${actualSize} B","unpackedSize":"68 B"}`, `{"limit":"${actualSize} B","packageSize":"${actualSize} B","unpackedSize":"68 B"}`,
) )
}) })
it('outputs expected messaging', async () => { it('outputs expected messaging', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
const mockWarn = jest.spyOn(console, 'warn') const mockWarn = jest.spyOn(console, 'warn')
const mockError = jest.spyOn(console, 'error') const mockError = jest.spyOn(console, 'error')
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await expect(async () => await expect(async () => packwatch({ cwd: workspacePath })).rejects.toThrow()
packwatch({ cwd: workspacePath }),
).rejects.toThrow()
expect(mockWarn.mock.calls).toHaveLength(1) expect(mockWarn.mock.calls).toHaveLength(1)
expect(mockWarn.mock.calls[0][0]).toEqual( expect(mockWarn.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(
/No Manifest to compare against! Current package stats written to \.packwatch\.json!\nPackage size \(\d+ B\) adopted as new limit\./, /No Manifest to compare against! Current package stats written to \.packwatch\.json!\nPackage size \(\d+ B\) adopted as new limit\./,
), ),
) )
expect(mockError.mock.calls).toHaveLength(1) expect(mockError.mock.calls).toHaveLength(1)
expect(mockError.mock.calls[0][0]).toEqual( expect(mockError.mock.calls[0][0]).toEqual(
expect.stringMatching( 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!', '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!',
), ),
) )
}) })
it('outputs expected messaging when not updating the manifest', async () => { it('outputs expected messaging when not updating the manifest', async () => {
const mockWarn = jest.spyOn(console, 'warn') const mockWarn = jest.spyOn(console, 'warn')
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await packwatch({ cwd: workspacePath, isUpdatingManifest: true }) await packwatch({ cwd: workspacePath, isUpdatingManifest: true })
expect(mockWarn.mock.calls).toHaveLength(1) expect(mockWarn.mock.calls).toHaveLength(1)
expect(mockWarn.mock.calls[0][0]).toEqual( expect(mockWarn.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(
/No Manifest to compare against! Current package stats written to \.packwatch\.json!\nPackage size \(\d+ B\) adopted as new limit\./, /No Manifest to compare against! Current package stats written to \.packwatch\.json!\nPackage size \(\d+ B\) adopted as new limit\./,
), ),
) )
}) })
}) })
describe('with manifest', () => { describe('with manifest', () => {
it('messages when the size is equal to the limit', async () => { it('messages when the size is equal to the limit', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
const mockLogger = jest.spyOn(console, 'log') const mockLogger = jest.spyOn(console, 'log')
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await createManifest(workspacePath, { await createManifest(workspacePath, {
limit: `${actualSize}B`, limit: `${actualSize}B`,
packageSize: `${actualSize}B`, packageSize: `${actualSize}B`,
packageSizeBytes: Number(actualSize), packageSizeBytes: Number(actualSize),
unpackedSize: '150B', unpackedSize: '150B',
unpackedSizeBytes: 150, unpackedSizeBytes: 150,
}) })
await packwatch({ cwd: workspacePath }) await packwatch({ cwd: workspacePath })
expect(mockLogger.mock.calls).toHaveLength(1) expect(mockLogger.mock.calls).toHaveLength(1)
expect(mockLogger.mock.calls[0][0]).toEqual( expect(mockLogger.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(/Nothing to report! Your package is the same size as the latest manifest reports!/),
/Nothing to report! Your package is the same size as the latest manifest reports!/, )
), })
)
})
it('messages when the size is lower than the limit (no growth)', async () => { it('messages when the size is lower than the limit (no growth)', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
const mockLogger = jest.spyOn(console, 'log') const mockLogger = jest.spyOn(console, 'log')
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await createManifest(workspacePath, { await createManifest(workspacePath, {
limit: '170B', limit: '170B',
packageSize: `${actualSize}B`, packageSize: `${actualSize}B`,
packageSizeBytes: Number(actualSize), packageSizeBytes: Number(actualSize),
unpackedSize: '150B', unpackedSize: '150B',
unpackedSizeBytes: 150, unpackedSizeBytes: 150,
}) })
await packwatch({ cwd: workspacePath }) await packwatch({ cwd: workspacePath })
expect(mockLogger.mock.calls).toHaveLength(1) expect(mockLogger.mock.calls).toHaveLength(1)
expect(mockLogger.mock.calls[0][0]).toEqual( expect(mockLogger.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(
/Nothing to report! Your package is the same size as the latest manifest reports! \(Limit: 170B\)/, /Nothing to report! Your package is the same size as the latest manifest reports! \(Limit: 170B\)/,
), ),
) )
}) })
it('messages when the size is lower than the limit (growth)', async () => { it('messages when the size is lower than the limit (growth)', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
const mockLogger = jest.spyOn(console, 'log') const mockLogger = jest.spyOn(console, 'log')
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await createManifest(workspacePath, { await createManifest(workspacePath, {
limit: '180B', limit: '180B',
packageSize: '150B', packageSize: '150B',
packageSizeBytes: 150, packageSizeBytes: 150,
unpackedSize: '140B', unpackedSize: '140B',
unpackedSizeBytes: 140, unpackedSizeBytes: 140,
}) })
await packwatch({ cwd: workspacePath }) await packwatch({ cwd: workspacePath })
expect(mockLogger.mock.calls).toHaveLength(1) expect(mockLogger.mock.calls).toHaveLength(1)
expect(mockLogger.mock.calls[0][0]).toEqual( expect(mockLogger.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(/Your package grew! \d+ B > 150B \(Limit: 180B\)/),
/Your package grew! \d+ B > 150B \(Limit: 180B\)/, )
), })
) it('messages when the size is lower than the limit (shrinkage)', async () => {
}) const workspacePath = await prepareWorkspace()
it('messages when the size is lower than the limit (shrinkage)', async () => { const mockLogger = jest.spyOn(console, 'log')
const workspacePath = await prepareWorkspace() await createPackageJson(workspacePath)
const mockLogger = jest.spyOn(console, 'log') await createManifest(workspacePath, {
await createPackageJson(workspacePath) limit: '180B',
await createManifest(workspacePath, { packageSize: '170B',
limit: '180B', packageSizeBytes: 170,
packageSize: '170B', unpackedSize: '140B',
packageSizeBytes: 170, unpackedSizeBytes: 140,
unpackedSize: '140B', })
unpackedSizeBytes: 140,
})
await packwatch({ cwd: workspacePath }) await packwatch({ cwd: workspacePath })
expect(mockLogger.mock.calls).toHaveLength(1) expect(mockLogger.mock.calls).toHaveLength(1)
expect(mockLogger.mock.calls[0][0]).toEqual( expect(mockLogger.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(/Your package shrank! \d+ B < 170B \(Limit: 180B\)/),
/Your package shrank! \d+ B < 170B \(Limit: 180B\)/, )
), })
) it('messages when the size exceeds the limit', async () => {
}) const workspacePath = await prepareWorkspace()
it('messages when the size exceeds the limit', async () => { const mockError = jest.spyOn(console, 'error')
const workspacePath = await prepareWorkspace() await createPackageJson(workspacePath)
const mockError = jest.spyOn(console, 'error') await createManifest(workspacePath, {
await createPackageJson(workspacePath) limit: '10B',
await createManifest(workspacePath, { packageSize: '170B',
limit: '10B', packageSizeBytes: 170,
packageSize: '170B', unpackedSize: '140B',
packageSizeBytes: 170, unpackedSizeBytes: 140,
unpackedSize: '140B', })
unpackedSizeBytes: 140,
})
await expect(async () => await expect(async () => packwatch({ cwd: workspacePath })).rejects.toThrow('PACKAGE_EXCEEDS_LIMIT')
packwatch({ cwd: workspacePath }), expect(mockError.mock.calls).toHaveLength(1)
).rejects.toThrow('PACKAGE_EXCEEDS_LIMIT') expect(mockError.mock.calls[0][0]).toEqual(
expect(mockError.mock.calls).toHaveLength(1) expect.stringMatching(
expect(mockError.mock.calls[0][0]).toEqual( /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!/,
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!/, )
), })
)
})
it('messages when updating the manifest', async () => { it('messages when updating the manifest', async () => {
const workspacePath = await prepareWorkspace() const workspacePath = await prepareWorkspace()
const mockLogger = jest.spyOn(console, 'log') const mockLogger = jest.spyOn(console, 'log')
await createPackageJson(workspacePath) await createPackageJson(workspacePath)
await createManifest(workspacePath, { await createManifest(workspacePath, {
limit: '10B', limit: '10B',
packageSize: '170B', packageSize: '170B',
packageSizeBytes: 170, packageSizeBytes: 170,
unpackedSize: '140B', unpackedSize: '140B',
unpackedSizeBytes: 140, unpackedSizeBytes: 140,
}) })
await packwatch({ cwd: workspacePath, isUpdatingManifest: true }) await packwatch({ cwd: workspacePath, isUpdatingManifest: true })
expect(mockLogger.mock.calls).toHaveLength(1) expect(mockLogger.mock.calls).toHaveLength(1)
expect(mockLogger.mock.calls[0][0]).toEqual( expect(mockLogger.mock.calls[0][0]).toEqual(
expect.stringMatching( expect.stringMatching(/Updated the manifest! Package size: \d+ B, Limit: \d+ B/),
/Updated the manifest! Package size: \d+ B, Limit: \d+ B/, )
), })
) })
})
})
}) })

View file

@ -1,15 +1,12 @@
import { convertSizeToBytes } from '../src/utils' import { convertSizeToBytes } from '../src/utils'
describe('utils', () => { describe('utils', () => {
it.each` it.each`
initialSize | expectedSize initialSize | expectedSize
${'1 B'} | ${1} ${'1 B'} | ${1}
${'1 kB'} | ${1000} ${'1 kB'} | ${1000}
${'1 mB'} | ${1000000} ${'1 mB'} | ${1000000}
`( `('converts sizes properly ($initialSize -> $expectedSize)', ({ initialSize, expectedSize }) => {
'converts sizes properly ($initialSize -> $expectedSize)', expect(convertSizeToBytes(initialSize)).toEqual(expectedSize)
({ initialSize, expectedSize }) => { })
expect(convertSizeToBytes(initialSize)).toEqual(expectedSize)
},
)
}) })

View file

@ -1,7 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["src", "tests", ".eslintrc.js"],
"exclude": [
"dist/**/*"
]
}

1941
yarn.lock

File diff suppressed because it is too large Load diff