I am trying to write the following code with fp-ts.
imperative:
export async function runTest(globString) {
let passed = 0;
let failed = 0;
const files = glob.sync(globString);
for (let i = 0; i < files.length; i++) {
// eslint-disable-next-line no-await-in-loop
const module = await import(`./${path.relative(__dirname, files[i])}`);
for (let z = 0; z < Object.keys(module).length; z++) {
const testFn = Object.keys(module)[z];
// eslint-disable-next-line no-await-in-loop
const result = await module[testFn]()
// eslint-disable-next-line no-plusplus
if (result) { passed++ } else { failed++ };
console.log(`${result ? `✅` : `❌`} ${module[testFn].description || testFn}`)
}
}
console.log(`✅ ${passed} tests passed`);
console.log(`❌ ${failed} tests failed`);
}
the functions applied can be divided into two:
the one that imports the file from the glob. the second that runs the function.
We can even omit the console logs, I am stuck where I should read the right values but I am not what should to that the data out of this Right, and also eventually have the Left in a separated array. Any ideas?
const importModule = (string) => import(`./${path.relative(__dirname, string)}`)
export const runTest = (globString) => pipe(
glob.sync(globString),
AR.map(TE.tryCatchK(importModule, id)),
AR.map(TE.bimap(id, Object.values)),
AR.map(TE.bimap(id, AR.map(fn => [fn(), fn.name]))),
async a => console.log(await a[0]()) //{_tag: 'Right', right: Array(15)}
)
//number of items is correct but I am stuck here.
EDIT:
got the code improved now it works by capturing the errors into the Eithers and I do have an array of Eithers.
export const runTest = (globString) => pipe(
glob.sync(globString),
x => [...x, 'tras'], //last item will throw an error it is on purpose
AR.map(TE.tryCatchK(async str => Object.values((await importModule(str))), id)),
AR.sequence(T.ApplicativePar),
async a => (await a()).map(console.log)
)
Now the rights in the Array are arrays as well, so I have Task<Array<Either<E,Array>>> and I need Task<Array<Either<E,Function>, problem now is that if I try to sequence I lose the rights
For anyone wondering I ended up with the following.
const safeRunFn = f => TE.tryCatchK(
async (s) => await f() && `✅ ${f.description || f.name} - passed`,
(e) => `❌ ${f.description || f.name} - failed \n${e}`
)(f);
const safeImport = z => TE.tryCatchK(
(s) => import(`./${path.relative(__dirname, s)}`),
(e) => `❌ ${z} - failed \n${e}`
)(z);
export const runTest = (globString) => pipe(
glob.sync(globString),
x => [...x, 'tras'],
A.map(safeImport),
A.map(TE.map(Object.values)),
A.map(TE.chain(TE.traverseArray(safeRunFn))),
A.map(TE.match(id, id)),
T.sequenceArray,
T.map(x => x.flat())
//A.flatten throws the error below, not sure why.
//Uncaught TypeError TypeError: CreateListFromArrayLike called on non-object
)
Any ideas how this can be improved are welcome.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.