diff --git a/pkg/fs/src/plugin.ts b/pkg/fs/src/plugin.ts index 64cf494e..b57fb5eb 100644 --- a/pkg/fs/src/plugin.ts +++ b/pkg/fs/src/plugin.ts @@ -46,6 +46,15 @@ const readJSON = async (safePath: string) => { return JSON.parse(str); }; +const checkFileExists = async (safePath: string) => { + try { + await fspkg.stat(safePath); + } catch { + return false; + } + return true; +} + const p = new Plugin(); /** @@ -155,4 +164,30 @@ export const listDirectoryContent = p.new(['path'], 'list directory content', as return ctx.pass(result); }); +/** + * @internal + */ +export const verifyFileExists = p.new(['path'], 'verify file exists', async (ctx) => { + const unsafe = ctx.fetch('path'); + if (typeof unsafe !== 'string') return ctx.fail('path must be string'); + + const { filepath, error } = resolveFilepath(unsafe); + if (!filepath) return ctx.fail(error); + if (!(await checkFileExists(filepath))) return ctx.fail('no such file or directory: '+filepath); + return ctx.pass(null); +}); + +/** + * @internal + */ +export const verifyFileDoesNotExist = p.new(['path'], 'verify file does not exist', async (ctx) => { + const unsafe = ctx.fetch('path'); + if (typeof unsafe !== 'string') return ctx.fail('path must be string'); + + const { filepath, error } = resolveFilepath(unsafe); + if (!filepath) return ctx.fail(error); + if (await checkFileExists(filepath)) return ctx.fail('file or directory found under: '+filepath); + return ctx.pass(null); +}); + export const fs = p; diff --git a/pkg/fs/test/e2e.ts b/pkg/fs/test/e2e.ts index 6393b6ce..c8dfc0f5 100644 --- a/pkg/fs/test/e2e.ts +++ b/pkg/fs/test/e2e.ts @@ -46,4 +46,74 @@ test.serial('Read verbatim file', async (t) => { content:"Hello World!\n", filename: "test.txt" }); -}); \ No newline at end of file +}); + +test.serial('path not a string', async (t) => { + process.env['FILES_DIR'] = "./test"; + const slangroom = new Slangroom(fs); + const fn = slangroom.execute(READ, { + data: { + filename: { + "path": "test.txt" + } + }, + }); + const error = await t.throwsAsync(fn); + t.is((error as Error).message, 'path must be string'); +}); + +test.serial('File exists', async (t) => { + const verifyExists = `Rule unknown ignore +Given I send path 'filename' and verify file exists +Given I have a 'string' named 'filename' +Then print the 'filename' +Then print the string 'the file exists' +` + process.env['FILES_DIR'] = "./test"; + const slangroom = new Slangroom(fs); + const resultExists = slangroom.execute(verifyExists, { + data: { + filename: "test.txt" + }, + }); + const res = await resultExists; + t.deepEqual(res.result, { + filename: 'test.txt', + output: ["the_file_exists"] + }); + const resultNotExists = slangroom.execute(verifyExists, { + data: { + filename: "test_not_exist.txt" + }, + }); + const error = await t.throwsAsync(resultNotExists); + t.is((error as Error).message, 'no such file or directory: test/test_not_exist.txt'); +}); + +test.serial('File does not exist', async (t) => { + const verifyDoesNotExists = `Rule unknown ignore +Given I send path 'filename' and verify file does not exist +Given I have a 'string' named 'filename' +Then print the 'filename' +Then print the string 'the file does not exist' +` + process.env['FILES_DIR'] = "./test"; + const slangroom = new Slangroom(fs); + const resultExists = slangroom.execute(verifyDoesNotExists, { + data: { + filename: "test.txt" + }, + }); + const error = await t.throwsAsync(resultExists); + t.is((error as Error).message, 'file or directory found under: test/test.txt'); + const resultNotExists = slangroom.execute(verifyDoesNotExists, { + data: { + filename: "test_not_exist.txt" + }, + }); + const res = await await resultNotExists; + t.deepEqual(res.result, { + filename: 'test_not_exist.txt', + output: ["the_file_does_not_exist"] + }); +});