Merge pull request 'fs functions' (#44) from fs into main
Reviewed-on: #44
This commit is contained in:
commit
8008f37f16
|
|
@ -1,4 +1,4 @@
|
||||||
import { type Value, toString, toValue } from 'reefvm'
|
import { type Value, toString } from 'reefvm'
|
||||||
|
|
||||||
export const dict = {
|
export const dict = {
|
||||||
keys: (dict: Record<string, any>) => Object.keys(dict),
|
keys: (dict: Record<string, any>) => Object.keys(dict),
|
||||||
|
|
|
||||||
128
src/prelude/fs.ts
Normal file
128
src/prelude/fs.ts
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
import { join, resolve, basename, dirname, extname } from 'path'
|
||||||
|
import {
|
||||||
|
readdirSync, mkdirSync, rmdirSync,
|
||||||
|
readFileSync, writeFileSync, appendFileSync,
|
||||||
|
rmSync, copyFileSync,
|
||||||
|
statSync, lstatSync, chmodSync, symlinkSync, readlinkSync,
|
||||||
|
watch
|
||||||
|
} from "fs"
|
||||||
|
|
||||||
|
export const fs = {
|
||||||
|
// Directory operations
|
||||||
|
ls: (path: string) => readdirSync(path),
|
||||||
|
mkdir: (path: string) => mkdirSync(path, { recursive: true }),
|
||||||
|
rmdir: (path: string) => rmdirSync(path === '/' || path === '' ? '/tmp/*' : path, { recursive: true }),
|
||||||
|
pwd: () => process.cwd(),
|
||||||
|
cd: (path: string) => process.chdir(path),
|
||||||
|
|
||||||
|
// Reading
|
||||||
|
read: (path: string) => readFileSync(path, 'utf-8'),
|
||||||
|
cat: (path: string) => { }, // added below
|
||||||
|
'read-bytes': (path: string) => [...readFileSync(path)],
|
||||||
|
|
||||||
|
// Writing
|
||||||
|
write: (path: string, content: string) => writeFileSync(path, content),
|
||||||
|
append: (path: string, content: string) => appendFileSync(path, content),
|
||||||
|
|
||||||
|
// File operations
|
||||||
|
delete: (path: string) => rmSync(path),
|
||||||
|
rm: (path: string) => { }, // added below
|
||||||
|
copy: (from: string, to: string) => copyFileSync(from, to),
|
||||||
|
move: (from: string, to: string) => {
|
||||||
|
fs.copy(from, to)
|
||||||
|
fs.rm(from)
|
||||||
|
},
|
||||||
|
mv: (from: string, to: string) => { }, // added below
|
||||||
|
|
||||||
|
// Path operations
|
||||||
|
basename: (path: string) => basename(path),
|
||||||
|
dirname: (path: string) => dirname(path),
|
||||||
|
extname: (path: string) => extname(path),
|
||||||
|
join: (...paths: string[]) => join(...paths),
|
||||||
|
resolve: (...paths: string[]) => resolve(...paths),
|
||||||
|
|
||||||
|
// File info
|
||||||
|
stat: (path: string) => {
|
||||||
|
try {
|
||||||
|
const stats = statSync(path)
|
||||||
|
const record = Object.fromEntries(Object.entries(stats))
|
||||||
|
record['atime'] = record['atimeMs']
|
||||||
|
record['ctime'] = record['ctimeMs']
|
||||||
|
record['mtime'] = record['mtimeMs']
|
||||||
|
|
||||||
|
delete record['atimeMs']
|
||||||
|
delete record['ctimeMs']
|
||||||
|
delete record['mtimeMs']
|
||||||
|
|
||||||
|
return record
|
||||||
|
} catch {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
'exists?': (path: string) => {
|
||||||
|
try {
|
||||||
|
statSync(path)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'file?': (path: string) => {
|
||||||
|
try { return statSync(path).isFile() }
|
||||||
|
catch { return false }
|
||||||
|
},
|
||||||
|
'dir?': (path: string) => {
|
||||||
|
try { return statSync(path).isDirectory() }
|
||||||
|
catch { return false }
|
||||||
|
},
|
||||||
|
'symlink?': (path: string) => {
|
||||||
|
try { return lstatSync(path).isSymbolicLink() }
|
||||||
|
catch { return false }
|
||||||
|
},
|
||||||
|
'exec?': (path: string) => {
|
||||||
|
try {
|
||||||
|
const stats = statSync(path)
|
||||||
|
return !!(stats.mode & 0o111)
|
||||||
|
}
|
||||||
|
catch { return false }
|
||||||
|
},
|
||||||
|
size: (path: string) => {
|
||||||
|
try { return statSync(path).size }
|
||||||
|
catch { return 0 }
|
||||||
|
},
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
chmod: (path: string, mode: number | string) => {
|
||||||
|
const numMode = typeof mode === 'string' ? parseInt(mode, 8) : mode
|
||||||
|
chmodSync(path, numMode)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Symlinks
|
||||||
|
symlink: (target: string, path: string) => symlinkSync(target, path),
|
||||||
|
readlink: (path: string) => readlinkSync(path, 'utf-8'),
|
||||||
|
|
||||||
|
// Other
|
||||||
|
glob: (pattern: string) => {
|
||||||
|
const dir = pattern.substring(0, pattern.lastIndexOf('/'))
|
||||||
|
const match = pattern.substring(pattern.lastIndexOf('/') + 1)
|
||||||
|
|
||||||
|
if (!match.includes('*')) throw new Error('only * patterns supported')
|
||||||
|
|
||||||
|
const ext = match.split('*').pop()!
|
||||||
|
return readdirSync(dir)
|
||||||
|
.filter((f) => f.endsWith(ext))
|
||||||
|
.map((f) => join(dir, f))
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: (path: string, callback: Function) =>
|
||||||
|
watch(path, (event, filename) => callback(event, filename)),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; (fs as any).cat = fs.read
|
||||||
|
; (fs as any).mv = fs.move
|
||||||
|
; (fs as any).cp = fs.copy
|
||||||
|
; (fs as any).rm = fs.delete
|
||||||
|
|
@ -6,6 +6,7 @@ import {
|
||||||
} from 'reefvm'
|
} from 'reefvm'
|
||||||
|
|
||||||
import { dict } from './dict'
|
import { dict } from './dict'
|
||||||
|
import { fs } from './fs'
|
||||||
import { json } from './json'
|
import { json } from './json'
|
||||||
import { load } from './load'
|
import { load } from './load'
|
||||||
import { list } from './list'
|
import { list } from './list'
|
||||||
|
|
@ -14,6 +15,7 @@ import { str } from './str'
|
||||||
|
|
||||||
export const globals = {
|
export const globals = {
|
||||||
dict,
|
dict,
|
||||||
|
fs,
|
||||||
json,
|
json,
|
||||||
load,
|
load,
|
||||||
list,
|
list,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ export const load = async function (this: VM, path: string): Promise<Record<stri
|
||||||
const scope = this.scope
|
const scope = this.scope
|
||||||
const pc = this.pc
|
const pc = this.pc
|
||||||
|
|
||||||
const fullPath = resolve(path) + '.sh'
|
let fullPath = resolve(path)
|
||||||
|
if (!path.includes('.')) fullPath += '.sh'
|
||||||
|
|
||||||
const code = readFileSync(fullPath, 'utf-8')
|
const code = readFileSync(fullPath, 'utf-8')
|
||||||
|
|
||||||
this.pc = this.instructions.length
|
this.pc = this.instructions.length
|
||||||
|
|
|
||||||
329
src/prelude/tests/fs.test.ts
Normal file
329
src/prelude/tests/fs.test.ts
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
import { expect, describe, test, beforeEach, afterEach } from 'bun:test'
|
||||||
|
import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs'
|
||||||
|
import { join, resolve } from 'path'
|
||||||
|
import { fs } from '../fs'
|
||||||
|
|
||||||
|
const TEST_DIR = resolve('./tmp/shrimp-fs-test')
|
||||||
|
const CWD = process.cwd()
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
if (existsSync(TEST_DIR)) {
|
||||||
|
rmSync(TEST_DIR, { recursive: true })
|
||||||
|
}
|
||||||
|
mkdirSync(TEST_DIR, { recursive: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.chdir(CWD)
|
||||||
|
if (existsSync(TEST_DIR)) {
|
||||||
|
rmSync(TEST_DIR, { recursive: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - directory operations', () => {
|
||||||
|
test('fs.ls lists directory contents', () => {
|
||||||
|
writeFileSync(join(TEST_DIR, 'file1.txt'), 'content1')
|
||||||
|
writeFileSync(join(TEST_DIR, 'file2.txt'), 'content2')
|
||||||
|
|
||||||
|
const result = fs.ls(TEST_DIR)
|
||||||
|
expect(result).toContain('file1.txt')
|
||||||
|
expect(result).toContain('file2.txt')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.mkdir creates directory', () => {
|
||||||
|
const newDir = join(TEST_DIR, 'newdir')
|
||||||
|
fs.mkdir(newDir)
|
||||||
|
expect(existsSync(newDir)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.rmdir removes empty directory', () => {
|
||||||
|
const dir = join(TEST_DIR, 'toremove')
|
||||||
|
mkdirSync(dir)
|
||||||
|
fs.rmdir(dir)
|
||||||
|
expect(existsSync(dir)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.pwd returns current working directory', () => {
|
||||||
|
const result = fs.pwd()
|
||||||
|
expect(typeof result).toBe('string')
|
||||||
|
expect(result.length).toBeGreaterThan(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.cd changes current working directory', () => {
|
||||||
|
const originalCwd = process.cwd()
|
||||||
|
fs.cd(TEST_DIR)
|
||||||
|
expect(process.cwd()).toBe(TEST_DIR)
|
||||||
|
process.chdir(originalCwd) // restore
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - reading', () => {
|
||||||
|
test('fs.read reads file contents as string', () => {
|
||||||
|
const file = join(TEST_DIR, 'test.txt')
|
||||||
|
writeFileSync(file, 'hello world')
|
||||||
|
|
||||||
|
const result = fs.read(file)
|
||||||
|
expect(result).toBe('hello world')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.cat is alias for fs.read', () => {
|
||||||
|
const file = join(TEST_DIR, 'test.txt')
|
||||||
|
writeFileSync(file, 'hello world')
|
||||||
|
|
||||||
|
const result = fs.cat(file)
|
||||||
|
expect(result).toBe('hello world')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.read-bytes reads file as buffer', () => {
|
||||||
|
const file = join(TEST_DIR, 'test.bin')
|
||||||
|
writeFileSync(file, Buffer.from([1, 2, 3, 4]))
|
||||||
|
|
||||||
|
const result = fs['read-bytes'](file)
|
||||||
|
expect(result).toBeInstanceOf(Array)
|
||||||
|
expect(result).toEqual([1, 2, 3, 4])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - writing', () => {
|
||||||
|
test('fs.write writes string to file', async () => {
|
||||||
|
const file = join(TEST_DIR, 'output.txt')
|
||||||
|
fs.write(file, 'test content')
|
||||||
|
|
||||||
|
const content = Bun.file(file).text()
|
||||||
|
expect(await content).toBe('test content')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.append appends to existing file', async () => {
|
||||||
|
const file = join(TEST_DIR, 'append.txt')
|
||||||
|
writeFileSync(file, 'first')
|
||||||
|
fs.append(file, ' second')
|
||||||
|
|
||||||
|
const content = await Bun.file(file).text()
|
||||||
|
expect(content).toBe('first second')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - file operations', () => {
|
||||||
|
test('fs.rm removes file', () => {
|
||||||
|
const file = join(TEST_DIR, 'remove.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
fs.rm(file)
|
||||||
|
expect(existsSync(file)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.delete is alias for fs.rm', () => {
|
||||||
|
const file = join(TEST_DIR, 'delete.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
fs.delete(file)
|
||||||
|
expect(existsSync(file)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.copy copies file', async () => {
|
||||||
|
const src = join(TEST_DIR, 'source.txt')
|
||||||
|
const dest = join(TEST_DIR, 'dest.txt')
|
||||||
|
writeFileSync(src, 'content')
|
||||||
|
|
||||||
|
fs.copy(src, dest)
|
||||||
|
expect(await Bun.file(dest).text()).toBe('content')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.cp is alias for fs.copy', async () => {
|
||||||
|
const src = join(TEST_DIR, 'source2.txt')
|
||||||
|
const dest = join(TEST_DIR, 'dest2.txt')
|
||||||
|
writeFileSync(src, 'content')
|
||||||
|
|
||||||
|
fs.cp(src, dest)
|
||||||
|
expect(await Bun.file(dest).text()).toBe('content')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.move moves file', async () => {
|
||||||
|
const src = join(TEST_DIR, 'source.txt')
|
||||||
|
const dest = join(TEST_DIR, 'moved.txt')
|
||||||
|
writeFileSync(src, 'content')
|
||||||
|
|
||||||
|
fs.move(src, dest)
|
||||||
|
expect(existsSync(src)).toBe(false)
|
||||||
|
expect(await Bun.file(dest).text()).toBe('content')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.mv is alias for fs.move', async () => {
|
||||||
|
const src = join(TEST_DIR, 'source2.txt')
|
||||||
|
const dest = join(TEST_DIR, 'moved2.txt')
|
||||||
|
writeFileSync(src, 'content')
|
||||||
|
|
||||||
|
fs.mv(src, dest)
|
||||||
|
expect(existsSync(src)).toBe(false)
|
||||||
|
expect(await Bun.file(dest).text()).toBe('content')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - path operations', () => {
|
||||||
|
test('fs.basename extracts filename from path', () => {
|
||||||
|
expect(fs.basename('/path/to/file.txt')).toBe('file.txt')
|
||||||
|
expect(fs.basename('/path/to/dir/')).toBe('dir')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.dirname extracts directory from path', () => {
|
||||||
|
expect(fs.dirname('/path/to/file.txt')).toBe('/path/to')
|
||||||
|
expect(fs.dirname('/path/to/dir/')).toBe('/path/to')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.extname extracts file extension', () => {
|
||||||
|
expect(fs.extname('file.txt')).toBe('.txt')
|
||||||
|
expect(fs.extname('file.tar.gz')).toBe('.gz')
|
||||||
|
expect(fs.extname('noext')).toBe('')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.join joins path segments', () => {
|
||||||
|
expect(fs.join('path', 'to', 'file.txt')).toBe('path/to/file.txt')
|
||||||
|
expect(fs.join('/absolute', 'path')).toBe('/absolute/path')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.resolve resolves to absolute path', () => {
|
||||||
|
const result = fs.resolve('relative', 'path')
|
||||||
|
expect(result.startsWith('/')).toBe(true)
|
||||||
|
expect(result).toContain('relative')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - file info', () => {
|
||||||
|
test('fs.stat returns file stats', () => {
|
||||||
|
const file = join(TEST_DIR, 'stat.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
const stats = fs.stat(file)
|
||||||
|
expect(stats).toHaveProperty('size')
|
||||||
|
expect(stats).toHaveProperty('mtime')
|
||||||
|
expect(stats.size).toBe(7) // 'content' is 7 bytes
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.exists? checks if path exists', () => {
|
||||||
|
const file = join(TEST_DIR, 'exists.txt')
|
||||||
|
expect(fs['exists?'](file)).toBe(false)
|
||||||
|
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
expect(fs['exists?'](file)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.file? checks if path is a file', () => {
|
||||||
|
const file = join(TEST_DIR, 'isfile.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
expect(fs['file?'](file)).toBe(true)
|
||||||
|
expect(fs['file?'](TEST_DIR)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.dir? checks if path is a directory', () => {
|
||||||
|
const dir = join(TEST_DIR, 'isdir')
|
||||||
|
mkdirSync(dir)
|
||||||
|
|
||||||
|
expect(fs['dir?'](dir)).toBe(true)
|
||||||
|
expect(fs['dir?'](join(TEST_DIR, 'isfile.txt'))).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.symlink? checks if path is a symbolic link', () => {
|
||||||
|
const file = join(TEST_DIR, 'target.txt')
|
||||||
|
const link = join(TEST_DIR, 'link.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
fs.symlink(file, link)
|
||||||
|
expect(fs['symlink?'](link)).toBe(true)
|
||||||
|
expect(fs['symlink?'](file)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.exec? checks if file is executable', () => {
|
||||||
|
const file = join(TEST_DIR, 'script.sh')
|
||||||
|
writeFileSync(file, '#!/bin/bash\necho hello')
|
||||||
|
|
||||||
|
fs.chmod(file, 0o755)
|
||||||
|
expect(fs['exec?'](file)).toBe(true)
|
||||||
|
|
||||||
|
fs.chmod(file, 0o644)
|
||||||
|
expect(fs['exec?'](file)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.size returns file size in bytes', () => {
|
||||||
|
const file = join(TEST_DIR, 'sizeme.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
expect(fs.size(file)).toBe(7) // 'content' is 7 bytes
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - permissions', () => {
|
||||||
|
test('fs.chmod changes file permissions with octal number', () => {
|
||||||
|
const file = join(TEST_DIR, 'perms.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
fs.chmod(file, 0o755)
|
||||||
|
expect(fs['exec?'](file)).toBe(true)
|
||||||
|
|
||||||
|
fs.chmod(file, 0o644)
|
||||||
|
expect(fs['exec?'](file)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.chmod changes file permissions with string', () => {
|
||||||
|
const file = join(TEST_DIR, 'perms2.txt')
|
||||||
|
writeFileSync(file, 'content')
|
||||||
|
|
||||||
|
fs.chmod(file, '755')
|
||||||
|
expect(fs['exec?'](file)).toBe(true)
|
||||||
|
|
||||||
|
fs.chmod(file, '644')
|
||||||
|
expect(fs['exec?'](file)).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - symlinks', () => {
|
||||||
|
test('fs.symlink creates symbolic link', () => {
|
||||||
|
const target = join(TEST_DIR, 'target.txt')
|
||||||
|
const link = join(TEST_DIR, 'link.txt')
|
||||||
|
writeFileSync(target, 'content')
|
||||||
|
|
||||||
|
fs.symlink(target, link)
|
||||||
|
expect(fs['symlink?'](link)).toBe(true)
|
||||||
|
expect(fs.read(link)).toBe('content')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.readlink reads symbolic link target', () => {
|
||||||
|
const target = join(TEST_DIR, 'target.txt')
|
||||||
|
const link = join(TEST_DIR, 'link.txt')
|
||||||
|
writeFileSync(target, 'content')
|
||||||
|
|
||||||
|
fs.symlink(target, link)
|
||||||
|
expect(fs.readlink(link)).toBe(target)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fs - other', () => {
|
||||||
|
test('fs.glob matches file patterns', () => {
|
||||||
|
writeFileSync(join(TEST_DIR, 'file1.txt'), '')
|
||||||
|
writeFileSync(join(TEST_DIR, 'file2.txt'), '')
|
||||||
|
writeFileSync(join(TEST_DIR, 'file3.md'), '')
|
||||||
|
|
||||||
|
const result = fs.glob(join(TEST_DIR, '*.txt'))
|
||||||
|
expect(result).toHaveLength(2)
|
||||||
|
expect(result).toContain(join(TEST_DIR, 'file1.txt'))
|
||||||
|
expect(result).toContain(join(TEST_DIR, 'file2.txt'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fs.watch calls callback on file change', async () => {
|
||||||
|
const file = join(TEST_DIR, 'watch.txt')
|
||||||
|
writeFileSync(file, 'initial')
|
||||||
|
|
||||||
|
let called = false
|
||||||
|
const watcher = fs.watch(file, () => { called = true })
|
||||||
|
|
||||||
|
// Trigger change
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100))
|
||||||
|
writeFileSync(file, 'updated')
|
||||||
|
|
||||||
|
// Wait for watcher
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
|
||||||
|
expect(called).toBe(true)
|
||||||
|
watcher.close?.()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -1,41 +1,41 @@
|
||||||
import { expect, describe, test } from 'bun:test'
|
import { expect, describe, test } from 'bun:test'
|
||||||
import { globals } from '#prelude'
|
import { globals } from '#prelude'
|
||||||
|
|
||||||
describe('use', () => {
|
describe('loading a file', () => {
|
||||||
test(`imports all a file's functions`, async () => {
|
test(`imports all a file's functions`, async () => {
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
math.double 4
|
math.double 4
|
||||||
`).toEvaluateTo(8, globals)
|
`).toEvaluateTo(8, globals)
|
||||||
|
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
math.double (math.double 4)
|
math.double (math.double 4)
|
||||||
`).toEvaluateTo(16, globals)
|
`).toEvaluateTo(16, globals)
|
||||||
|
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
dbl = math.double
|
dbl = ref math.double
|
||||||
dbl (dbl 2)
|
dbl (dbl 2)
|
||||||
`).toEvaluateTo(8, globals)
|
`).toEvaluateTo(8, globals)
|
||||||
|
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
math.pi
|
math.pi
|
||||||
`).toEvaluateTo(3.14, globals)
|
`).toEvaluateTo(3.14, globals)
|
||||||
|
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
math | at 🥧
|
math | at 🥧
|
||||||
`).toEvaluateTo(3.14159265359, globals)
|
`).toEvaluateTo(3.14159265359, globals)
|
||||||
|
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
math.🥧
|
math.🥧
|
||||||
`).toEvaluateTo(3.14159265359, globals)
|
`).toEvaluateTo(3.14159265359, globals)
|
||||||
|
|
||||||
expect(`
|
expect(`
|
||||||
math = load ./src/prelude/tests/math
|
math = load ./src/prelude/tests/math.sh
|
||||||
math.add1 5
|
math.add1 5
|
||||||
`).toEvaluateTo(6, globals)
|
`).toEvaluateTo(6, globals)
|
||||||
})
|
})
|
||||||
Loading…
Reference in New Issue
Block a user