Comparing version 1.1.0 to 1.2.0
@@ -7,3 +7,7 @@ import { equal } from 'assert' | ||
const { main: withStub } = await import('./file-under-test.js') | ||
equal(withStub, 'processed bar padded') | ||
equal( | ||
withStub, | ||
'processed bar padded', | ||
'Original modules were loaded but expected stubs', | ||
) | ||
reset() | ||
@@ -10,0 +14,0 @@ // const { main: withoutStub } = await import('./file-under-test.js') |
import { readFile } from 'fs/promises' | ||
import { describe, it, beforeEach } from 'mocha' | ||
import { assert } from 'chai' | ||
import { load } from './load.js' | ||
import globalState from './global-state.js' | ||
import { loadFactory } from './load.js' | ||
import { stateFactory } from './state-factory.js' | ||
const { deepEqual } = assert | ||
const fibbleState = stateFactory() | ||
describe('load', () => { | ||
const load = loadFactory(fibbleState) | ||
const defaultLoad = (url, context) => ({ url, context, default: true }) | ||
beforeEach(() => { | ||
globalState.reset() | ||
fibbleState.reset() | ||
}) | ||
@@ -23,3 +26,3 @@ | ||
it('replaces replacements', async () => { | ||
globalState.replace('someUrl', { | ||
fibbleState.replace('someUrl', { | ||
prop1: 'whatever', | ||
@@ -42,3 +45,3 @@ prop2: 'whatever', | ||
it('handles default replacements', async () => { | ||
globalState.replace('someUrl', { | ||
fibbleState.replace('someUrl', { | ||
default: 'whatever', | ||
@@ -59,3 +62,3 @@ }) | ||
it('handles combined default and named replacements', async () => { | ||
globalState.replace('someUrl', { | ||
fibbleState.replace('someUrl', { | ||
default: 'whatever', | ||
@@ -62,0 +65,0 @@ prop1: 'whatever', |
import { readFile } from 'fs/promises' | ||
import fibbleState from './global-state.js' | ||
import { cleanURL } from './utils.js' | ||
@@ -23,11 +22,12 @@ | ||
function performReplacement(url) { | ||
function performReplacement(fibbleInfo, url) { | ||
const urlKey = cleanURL(url) | ||
const replacement = fibbleState.getReplacement(urlKey) | ||
const { default: defaultExport, ...rest } = replacement | ||
const defaultExportRows = | ||
defaultExport != null ? [createDefaultExport(urlKey)] : [] | ||
const defaultExportRows = fibbleInfo.hasDefaultReplacement(urlKey) | ||
? [createDefaultExport(urlKey)] | ||
: [] | ||
const namedExportRows = Object.keys(rest).map(createExportFor(urlKey)) | ||
const namedExportRows = fibbleInfo | ||
.getReplacementKeys(urlKey) | ||
.map(createExportFor(urlKey)) | ||
@@ -45,13 +45,15 @@ return shortCircuit([...defaultExportRows, ...namedExportRows].join('\n')) | ||
export async function load(url, context, nextLoad) { | ||
const cleanedURL = cleanURL(url) | ||
if (cleanedURL === replaceURL) { | ||
return generateReplaceFile(url) | ||
} | ||
export const loadFactory = (fibbleInfo) => { | ||
return function load(url, context, nextLoad) { | ||
const cleanedURL = cleanURL(url) | ||
if (cleanedURL === replaceURL) { | ||
return generateReplaceFile(url) | ||
} | ||
if (fibbleState.hasReplacement(cleanedURL)) { | ||
return performReplacement(url) | ||
if (fibbleInfo.hasReplacement(cleanedURL)) { | ||
return performReplacement(fibbleInfo, url) | ||
} | ||
return nextLoad(url, context) | ||
} | ||
return nextLoad(url, context) | ||
} |
@@ -1,2 +0,14 @@ | ||
export { resolve } from './resolve.js' | ||
export { load } from './load.js' | ||
import { loadFactory } from './load.js' | ||
import { resolveFactory } from './resolve.js' | ||
import { FibbleInfo } from './info.js' | ||
const fibbleInfo = new FibbleInfo() | ||
export async function initialize({ port }) { | ||
port.on('message', (values) => { | ||
fibbleInfo.setValues(values) | ||
}) | ||
} | ||
export const resolve = resolveFactory(fibbleInfo) | ||
export const load = loadFactory(fibbleInfo) |
@@ -1,2 +0,2 @@ | ||
import fibbleState from './global-state.js' | ||
import { stateFactory } from './state-factory.js' | ||
import { cleanURL } from './utils.js' | ||
@@ -6,2 +6,4 @@ | ||
const fibbleState = stateFactory() | ||
export async function replace(relPath, replacement) { | ||
@@ -8,0 +10,0 @@ const fullPath = await import.meta.resolve(relPath, parentURL) |
import { resolve as pathResolve } from 'path' | ||
import { describe, it, beforeEach } from 'mocha' | ||
import { assert } from 'chai' | ||
import { resolve } from './resolve.js' | ||
import globalState from './global-state.js' | ||
import { resolveFactory } from './resolve.js' | ||
import { stateFactory } from './state-factory.js' | ||
import { replaceFileURL } from './utils.js' | ||
@@ -11,2 +11,4 @@ | ||
describe('resolve', () => { | ||
const fibbleState = stateFactory() | ||
const resolve = resolveFactory(fibbleState) | ||
const sampleURL = new URL(`file://${pathResolve('./some-file.js')}`) | ||
@@ -26,3 +28,3 @@ const context = { parentURL: 'file:///tmp/a-caller.js' } | ||
beforeEach(() => { | ||
globalState.reset() | ||
fibbleState.reset() | ||
}) | ||
@@ -42,3 +44,3 @@ | ||
const resolvedURL = `${replacedFile} resolved with ${context.parentURL}` | ||
globalState.replace(resolvedURL, 'whatever') | ||
fibbleState.replace(resolvedURL, 'whatever') | ||
const result = await resolve(replacedFile, context, defaultResolver) | ||
@@ -45,0 +47,0 @@ const expected = { |
@@ -1,2 +0,1 @@ | ||
import fibbleState from './global-state.js' | ||
import { replaceFileURL } from './utils.js' | ||
@@ -6,14 +5,16 @@ | ||
export async function resolve(specifier, context, nextResolve) { | ||
const nr = await nextResolve(specifier, context) | ||
const { url } = nr | ||
export const resolveFactory = (fibbleInfo) => { | ||
return async function resolve(specifier, context, nextResolve) { | ||
const nr = await nextResolve(specifier, context) | ||
const { url } = nr | ||
if (url === replaceFileURL) { | ||
return shortCircuit(`${url}?__fibbleReplaceCaller=${context.parentURL}`) | ||
if (url === replaceFileURL) { | ||
return shortCircuit(`${url}?__fibbleReplaceCaller=${context.parentURL}`) | ||
} | ||
const count = fibbleInfo.getURLCount(url) | ||
return count != null | ||
? shortCircuit(`${url}?__fibbleCount=${count}`) | ||
: nextResolve(specifier, context) | ||
} | ||
const count = fibbleState.getURLCount(url) | ||
return count != null | ||
? shortCircuit(`${url}?__fibbleCount=${count}`) | ||
: nextResolve(specifier, context) | ||
} |
@@ -5,3 +5,3 @@ import { assert } from 'chai' | ||
const { equal, isUndefined, isTrue, isFalse } = assert | ||
const { deepEqual, equal, isUndefined, isTrue, isFalse } = assert | ||
@@ -15,6 +15,9 @@ describe('state', () => { | ||
const path = 'somePath' | ||
const pathWithDefault = 'somePathWithDefault' | ||
const replacement = { someKey: 'someValue' } | ||
const replacementWithDefault = { default: 'someDefault' } | ||
describe('set replacement', () => { | ||
beforeEach(() => { | ||
state.replace(path, replacement) | ||
state.replace(pathWithDefault, replacementWithDefault) | ||
}) | ||
@@ -41,2 +44,18 @@ | ||
}) | ||
it('allows retreivals of keys in the replacement', () => { | ||
const result = state.getReplacementKeys(path) | ||
deepEqual(result, ['someKey']) | ||
}) | ||
it('handles replacements without any keys', () => { | ||
deepEqual(state.getReplacementKeys(pathWithDefault), []) | ||
deepEqual(state.getReplacementKeys('someUnknownPath'), []) | ||
}) | ||
it('determines if a replacement has a default value', () => { | ||
isTrue(state.hasDefaultReplacement(pathWithDefault)) | ||
isFalse(state.hasDefaultReplacement(path)) | ||
isFalse(state.hasDefaultReplacement('someUnknownPath')) | ||
}) | ||
}) | ||
@@ -47,2 +66,3 @@ | ||
state.replace(path, replacement) | ||
state.replace(pathWithDefault, replacementWithDefault) | ||
state.reset(path, replacement) | ||
@@ -56,2 +76,10 @@ }) | ||
it('resets the replacement keys', () => { | ||
deepEqual(state.getReplacementKeys(path), []) | ||
}) | ||
it('resets the default replacement', () => { | ||
isFalse(state.hasDefaultReplacement(pathWithDefault)) | ||
}) | ||
it('increases the count for all repaced items', () => { | ||
@@ -58,0 +86,0 @@ equal(state.getURLCount(path), 2) |
@@ -1,11 +0,20 @@ | ||
export class FibbleState { | ||
import { FibbleInfo } from './info.js' | ||
export class FibbleState extends FibbleInfo { | ||
constructor() { | ||
super() | ||
this.replacements = {} | ||
this.counts = {} | ||
} | ||
replace(fullPath, replacement) { | ||
const allReplacementKeys = Object.keys(replacement) | ||
const replacementKeys = allReplacementKeys.filter((k) => k !== 'default') | ||
const currentCount = this.counts[fullPath] || 0 | ||
this.counts[fullPath] = currentCount + 1 | ||
this.replacements[fullPath] = replacement | ||
this.replacementKeys[fullPath] = replacementKeys | ||
if (allReplacementKeys.length > replacementKeys.length) { | ||
this.defaultReplacements[fullPath] = true | ||
} | ||
} | ||
@@ -18,2 +27,4 @@ | ||
this.replacements = {} | ||
this.replacementKeys = {} | ||
this.defaultReplacements = {} | ||
} | ||
@@ -28,10 +39,2 @@ | ||
} | ||
hasReplacement(fullPath) { | ||
return this.replacements[fullPath] != null | ||
} | ||
getURLCount(fullPath) { | ||
return this.counts[fullPath] | ||
} | ||
} |
{ | ||
"name": "fibble", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Small library to insert test doubles into your tests", | ||
@@ -19,7 +19,8 @@ "keywords": [ | ||
}, | ||
"./loader": "./lib/loader.js", | ||
"./loader": "./lib/legacy-loader.js", | ||
"./register": "./lib/register.js", | ||
"./package.json": "./package.json" | ||
}, | ||
"scripts": { | ||
"acceptance": "node --experimental-import-meta-resolve --loader fibble/loader acceptancetest/test.js", | ||
"acceptance": "./run-acceptance", | ||
"lint": "pnpm eslint . && pnpm prettier . --check && sort-package-json --check", | ||
@@ -30,5 +31,2 @@ "prepublishOnly": "pnpm lint && pnpm test", | ||
}, | ||
"dependencies": { | ||
"sort-package-json": "^2.1.0" | ||
}, | ||
"devDependencies": { | ||
@@ -40,7 +38,9 @@ "chai": "^4.3.7", | ||
"pad": "^3.2.0", | ||
"prettier": "^2.8.1" | ||
"prettier": "^2.8.1", | ||
"semver": "^7.5.4", | ||
"sort-package-json": "^2.1.0" | ||
}, | ||
"engines": { | ||
"node": "^16.12 || >18.6" | ||
"node": ">=16.12.0 <20.0.0 || >20.6.0" | ||
} | ||
} |
@@ -27,9 +27,24 @@ # fibble | ||
To use fibble you must start node with the fibble loader and an experimental flag. | ||
There are two modes available depending on the version of node you run. This is because node has changed their API for loaders. | ||
`node --experimental-import-meta-resolve --loader fibble/loader [my app]` | ||
#### modern mode | ||
Since these parameters are considered experimental in node, suppot might not be | ||
stable on upgrades of node. | ||
Use this with node version `18.19.0` and above. | ||
```bash | ||
node --experimental-import-meta-resolve --import fibble/register [my app] | ||
``` | ||
#### legacy mode | ||
Use this with node version `18.18.x` and below. | ||
```bash | ||
node --experimental-import-meta-resolve --loader fibble/loader [my app] | ||
``` | ||
#### non supported versons | ||
Fibble does not support node version `20.0.0` - `20.5.x`. | ||
### mocha example | ||
@@ -66,4 +81,4 @@ | ||
module.exports = { | ||
'node-option': ['experimental-import-meta-resolve', 'loader=fibble/loader'], | ||
'node-option': ['experimental-import-meta-resolve', 'import=fibble/register'], | ||
} | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24097
0
29
545
83
8
- Removedsort-package-json@^2.1.0
- Removeddetect-indent@7.0.1(transitive)
- Removeddetect-newline@4.0.1(transitive)
- Removedfdir@6.4.2(transitive)
- Removedget-stdin@9.0.0(transitive)
- Removedgit-hooks-list@3.1.0(transitive)
- Removedis-plain-obj@4.1.0(transitive)
- Removedpicomatch@4.0.2(transitive)
- Removedsemver@7.6.3(transitive)
- Removedsort-object-keys@1.1.3(transitive)
- Removedsort-package-json@2.12.0(transitive)
- Removedtinyglobby@0.2.10(transitive)