diff --git a/src/config/pragmas/shared.js b/src/config/pragmas/shared.js index 7d6d1e1..e299262 100644 --- a/src/config/pragmas/shared.js +++ b/src/config/pragmas/shared.js @@ -52,8 +52,8 @@ module.exports = function configureShared ({ arc, pragmas, inventory, errors }) } else if (foundPluginSrc) { if (!required) { - if (!is.exists(shared.src)) shared.src = src - if (!is.exists(shared.src)) return null + if (!is.exists(shared.src) && !is.exists(join(cwd, shared.src))) shared.src = src + if (!is.exists(shared.src) && !is.exists(join(cwd, shared.src))) return null } validate.shared(shared.src, cwd, errors, required) } diff --git a/test/unit/src/config/pragmas/shared-test.js b/test/unit/src/config/pragmas/shared-test.js index 77aecc1..b5affc6 100644 --- a/test/unit/src/config/pragmas/shared-test.js +++ b/test/unit/src/config/pragmas/shared-test.js @@ -1,5 +1,5 @@ let { join } = require('path') -let mockFs = require('mock-fs') +let mockTmp = require('mock-tmp') let parse = require('@architect/parser') let test = require('tape') let cwd = process.cwd() @@ -39,21 +39,23 @@ test('Project with any lambdae get a default @shared object', t => { test('Default dir is: src/shared (if present)', t => { t.plan(2) - let inventory = inventoryDefaults() + let cwd = mockTmp({ 'src/shared': {} }) + let inventory = inventoryDefaults({ cwd }) let arc let pragmas arc = parse(`@http`) pragmas = { http: populateHTTP({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'src/shared': {} }) + let shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, join(cwd, 'src', 'shared'), 'Returned correct default dir') t.deepEqual(shared.shared, [], 'Returned empty shared array') - mockFs.restore() + mockTmp.reset() }) test('Arc Static Asset Proxy is not included in @shared', t => { t.plan(4) - let inventory = inventoryDefaults() + let cwd = mockTmp({ 'src/shared': {} }) + let inventory = inventoryDefaults({ cwd }) let arc let pragmas arc = parse(`@http @@ -62,19 +64,20 @@ get /foo http get /*`) pragmas = { http: populateHTTP({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'src/shared': {} }) + let shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, join(cwd, 'src', 'shared'), 'Returned correct default dir') t.deepEqual(shared.shared, [], 'Returned empty shared array') let asap = pragmas.http.find(r => r.name === 'get /*') t.ok(asap.arcStaticAssetProxy, 'Got back ASAP') t.notOk(asap.config.shared, `Shared setting not enabled in ASAP`) - mockFs.restore() + mockTmp.reset() }) test(`@shared population: defaults to enabled (without @shared)`, t => { t.plan(6) - let inventory = inventoryDefaults() + let cwd = mockTmp({ 'src/shared': {} }) + let inventory = inventoryDefaults({ cwd }) let arc let pragmas let httpLambda = 'get /' @@ -86,7 +89,6 @@ test(`@shared population: defaults to enabled (without @shared)`, t => { lambdaSrcDirs } - mockFs({ 'src/shared': {} }) let shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, join(cwd, 'src', 'shared'), 'Returned correct default dir') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') @@ -96,12 +98,13 @@ test(`@shared population: defaults to enabled (without @shared)`, t => { t.ok(shared.shared.includes(fn2.src), `Got shared lambda: ${eventLambda}`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) t.ok(fn2.config.shared, `Shared setting enabled in lambda: ${eventLambda}`) - mockFs.restore() + mockTmp.reset() }) test(`@shared population: defaults to enabled (with empty @shared)`, t => { t.plan(6) - let inventory = inventoryDefaults() + let cwd = mockTmp({ 'src/shared': {} }) + let inventory = inventoryDefaults({ cwd }) let arc let pragmas let httpLambda = 'get /' @@ -113,7 +116,6 @@ test(`@shared population: defaults to enabled (with empty @shared)`, t => { lambdaSrcDirs } - mockFs({ 'src/shared': {} }) let shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, join(cwd, 'src', 'shared'), 'Returned correct default dir') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') @@ -123,12 +125,13 @@ test(`@shared population: defaults to enabled (with empty @shared)`, t => { t.ok(shared.shared.includes(fn2.src), `Got shared lambda: ${eventLambda}`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) t.ok(fn2.config.shared, `Shared setting enabled in lambda: ${eventLambda}`) - mockFs.restore() + mockTmp.reset() }) test(`@shared population: defaults to enabled (with src setting)`, t => { t.plan(6) - let inventory = inventoryDefaults() + let cwd = mockTmp({ 'foo/bar': {} }) + let inventory = inventoryDefaults({ cwd }) let arc let pragmas let httpLambda = 'get /' @@ -142,7 +145,6 @@ src foo/bar`) lambdaSrcDirs } - mockFs({ 'foo/bar': {} }) let shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, 'foo/bar', 'Got correct src dir back') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') @@ -152,16 +154,16 @@ src foo/bar`) t.ok(shared.shared.includes(fn2.src), `Got shared lambda: ${eventLambda}`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) t.ok(fn2.config.shared, `Shared setting enabled in lambda: ${eventLambda}`) - mockFs.restore() + mockTmp.reset() }) test(`@shared population: plugin setter`, t => { t.plan(20) - let inventory = inventoryDefaults() let setter = () => ({ src: 'foo/bar' }) - inventory.plugins = setterPluginSetup(setter) let arc + let cwd + let inventory let pragmas let shared let fn1, fn2 @@ -169,13 +171,17 @@ test(`@shared population: plugin setter`, t => { let eventLambda = 'an-event' // Basic plugin stuff + cwd = mockTmp({ 'foo/bar': {} }) + inventory = inventoryDefaults({ cwd }) + inventory.plugins = setterPluginSetup(setter) + arc = parse(`@http\n${httpLambda}\n@events\n${eventLambda}`) pragmas = { http: populateHTTP({ arc, inventory }), events: populateEvents({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'foo/bar': {} }) + shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, 'foo/bar', 'Got correct src dir back') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') @@ -185,46 +191,56 @@ test(`@shared population: plugin setter`, t => { t.ok(shared.shared.includes(fn2.src), `Got shared lambda: ${eventLambda}`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) t.ok(fn2.config.shared, `Shared setting enabled in lambda: ${eventLambda}`) - mockFs.restore() + mockTmp.reset() // Fall back to src/shared if specified dir is not found + cwd = mockTmp({ 'src/shared': {} }) + inventory = inventoryDefaults({ cwd }) + inventory.plugins = setterPluginSetup(setter) + arc = parse(`@http\n${httpLambda}\n@events\n${eventLambda}`) pragmas = { http: populateHTTP({ arc, inventory }), events: populateEvents({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'src/shared': {} }) shared = populateShared({ arc, pragmas, inventory }) t.ok(shared.src.endsWith(join('src', 'shared')), 'Got correct src dir back') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') - mockFs.restore() + mockTmp.reset() // Shared is null if setter doesn't set `required` flag and no dirs are found + cwd = mockTmp({ 'foo/bar': {} }) + inventory = inventoryDefaults({ cwd }) + inventory.plugins = setterPluginSetup(setter) + arc = parse(`@http\n${httpLambda}\n@events\n${eventLambda}`) pragmas = { http: populateHTTP({ arc, inventory }), events: populateEvents({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'foo/bar': {} }) // Just a control test! shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, 'foo/bar', 'Got correct src dir back') - mockFs.restore() + mockTmp.reset() shared = populateShared({ arc, pragmas, inventory }) t.equal(shared, null, 'shared is null') + mockTmp.reset() // Arc file wins + cwd = mockTmp({ 'foo/baz': {} }) + inventory = inventoryDefaults({ cwd }) + inventory.plugins = setterPluginSetup(setter) + arc = parse(`@http\n${httpLambda}\n@events\n${eventLambda} @shared -src foo/baz`) + src foo/baz`) pragmas = { http: populateHTTP({ arc, inventory }), events: populateEvents({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'foo/baz': {} }) shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, 'foo/baz', 'Got correct src dir back') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') @@ -234,9 +250,13 @@ src foo/baz`) t.ok(shared.shared.includes(fn2.src), `Got shared lambda: ${eventLambda}`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) t.ok(fn2.config.shared, `Shared setting enabled in lambda: ${eventLambda}`) - mockFs.restore() + mockTmp.reset() // cwd isn't concatenated when an absolute file path is returned + cwd = mockTmp({ 'foo/bar': {} }) + inventory = inventoryDefaults({ cwd }) + inventory.plugins = setterPluginSetup(setter) + let src = join(inventory._project.cwd, 'foo', 'bar') setter = () => ({ src }) inventory.plugins = setterPluginSetup(setter) @@ -245,19 +265,19 @@ src foo/baz`) http: populateHTTP({ arc, inventory }), lambdaSrcDirs } - mockFs({ 'foo/bar': {} }) shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, src, 'Got correct src dir back') t.equal(shared.shared.length, 1, 'Got correct number of lambdae with shared back') fn1 = pragmas.http.find(r => r.name === httpLambda) t.ok(shared.shared.includes(fn1.src), `Got shared lambda: ${httpLambda}`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) - mockFs.restore() + mockTmp.reset() }) test(`@shared population: lambdae not explicitly defined have shared disabled (with src setting)`, t => { t.plan(8) - let inventory = inventoryDefaults() + let cwd = mockTmp({ 'foo/bar': {} }) + let inventory = inventoryDefaults({ cwd }) let arc let pragmas let httpLambda = 'get /' @@ -282,7 +302,6 @@ src foo/bar`) lambdaSrcDirs } - mockFs({ 'foo/bar': {} }) let shared = populateShared({ arc, pragmas, inventory }) t.equal(shared.src, 'foo/bar', 'Got correct src dir back') t.equal(shared.shared.length, 2, 'Got correct number of lambdae with shared back') @@ -295,19 +314,22 @@ src foo/bar`) t.ok(fn1.config.shared, `Shared setting enabled in lambda: ${httpLambda}`) t.ok(fn2.config.shared, `Shared setting enabled in lambda: ${eventLambda}`) t.notOk(fn3.config.shared, `Shared setting not enabled in lambda: ${queueLambda}`) - mockFs.restore() + mockTmp.reset() }) test('@shared: validation errors', t => { t.plan(11) let arc + let cwd let pragmas let errors - let inventory = inventoryDefaults() + let inventory let updatePragmas = () => { pragmas = { http: populateHTTP({ arc, inventory }), lambdaSrcDirs } } + cwd = mockTmp({ 'src/shared': {} }) + inventory = inventoryDefaults({ cwd }) arc = parse(`@http get /foo @shared @@ -315,22 +337,24 @@ http put /bar`) errors = [] updatePragmas() - mockFs({ 'src/shared': {} }) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared lambda not found in corresponding pragma errored') - mockFs.restore() + mockTmp.reset() + cwd = mockTmp({ 'src/shared': {} }) + inventory = inventoryDefaults({ cwd }) arc = parse(`@http get /foo @shared hi`) errors = [] updatePragmas() - mockFs({ 'src/shared': {} }) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared invalid entry errored') - mockFs.restore() + mockTmp.reset() + cwd = mockTmp({ 'src/shared': {} }) + inventory = inventoryDefaults({ cwd }) arc = parse(`@http get /foo @shared @@ -338,10 +362,9 @@ static foo`) errors = [] updatePragmas() - mockFs({ 'src/shared': {} }) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared invalid pragma errored') - mockFs.restore() + mockTmp.reset() arc = parse(`@http get /foo @@ -349,21 +372,19 @@ get /foo src foo`) errors = [] updatePragmas() - mockFs({}) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared src dir must exist') - mockFs.restore() + cwd = mockTmp({ foo: 'hi!' }) + inventory = inventoryDefaults({ cwd }) arc = parse(`@http get /foo @shared src foo`) errors = [] updatePragmas() - mockFs({ foo: 'hi!' }) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared src must refer to a dir, not a file') - mockFs.restore() // From here on out we haven't needed to mock the filesystem since it should be returning errors prior to any folder existence checks; of course, update if that changes! arc = parse(`@http @@ -424,23 +445,25 @@ src true`) test('@shared: plugin errors', t => { t.plan(9) let arc + let cwd let pragmas let errors let setter - let inventory = inventoryDefaults() + let inventory let updatePragmas = () => { pragmas = { http: populateHTTP({ arc, inventory }), lambdaSrcDirs } } + cwd = mockTmp({ foo: {}, hi: {} }) + inventory = inventoryDefaults({ cwd }) arc = parse(`@http\nget /foo\n@shared\nsrc foo`) setter = () => ({ src: 'hi', required: true }) inventory.plugins = setterPluginSetup(setter) errors = [] updatePragmas() - mockFs({ foo: {}, hi: {} }) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors[0], '@shared src setting conflicts with plugin', '@shared src dir must exist if required flag is set') - mockFs.restore() + mockTmp.reset() arc = parse(`@http\nget /foo`) inventory.plugins = setterPluginSetup(setter) @@ -449,23 +472,27 @@ test('@shared: plugin errors', t => { populateShared({ arc, pragmas, inventory, errors }) t.equal(errors[0], 'Directory not found: hi', '@shared src dir must exist if required flag is set') + cwd = mockTmp({ foo: 'hi!' }) + inventory = inventoryDefaults({ cwd }) setter = () => ({ src: 'foo' }) inventory.plugins = setterPluginSetup(setter) errors = [] updatePragmas() - mockFs({ foo: 'hi!' }) populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared src must refer to a dir, not a file') - mockFs.restore() + mockTmp.reset() - // From here on out we haven't needed to mock the filesystem since it should be returning errors prior to any folder existence checks; of course, update if that changes! + cwd = mockTmp({ 'src/index.js': '// hi!' }) + inventory = inventoryDefaults({ cwd }) setter = () => ({ src: 'src/index.js' }) inventory.plugins = setterPluginSetup(setter) errors = [] updatePragmas() populateShared({ arc, pragmas, inventory, errors }) t.equal(errors.length, 1, '@shared src must be a directory') + mockTmp.reset() + // From here on out we haven't needed to mock the filesystem since it should be returning errors prior to any folder existence checks; of course, update if that changes! setter = () => ({ src: '.' }) inventory.plugins = setterPluginSetup(setter) errors = []