From b0c9a3810fcc7e749cb70c27947320f58114a352 Mon Sep 17 00:00:00 2001 From: Louise Foussat Date: Tue, 2 Mar 2021 19:17:52 +0000 Subject: [PATCH] add tell-it-cypher subject and tests --- js/tests/tell-it-cypher_test.mjs | 135 ++++++++++++++++++++++++++++++ subjects/tell-it-cypher/README.md | 18 ++++ 2 files changed, 153 insertions(+) create mode 100644 js/tests/tell-it-cypher_test.mjs create mode 100644 subjects/tell-it-cypher/README.md diff --git a/js/tests/tell-it-cypher_test.mjs b/js/tests/tell-it-cypher_test.mjs new file mode 100644 index 000000000..31157911a --- /dev/null +++ b/js/tests/tell-it-cypher_test.mjs @@ -0,0 +1,135 @@ +import * as cp from 'child_process' +import fs from 'fs/promises' +import { join, resolve, isAbsolute } from 'path' +import { tmpdir } from 'os' +import { promisify } from 'util' +const mkdir = fs.mkdir +const rmdir = fs.rmdir +const writeFile = fs.writeFile +const readFile = fs.readFile + +const exec = promisify(cp.exec) + +export const tests = [] +const name = 'tell-it-cypher' +// maybe get the sames from an api? like https://parser.name/ +const guests = [ + 'Shyam Langley', + 'Austin Harwood', + 'Reem Morgan', + 'Neal Chamberlain', + 'Ryan Walters', + 'Ocean Battle', + 'Ubaid Ballard', + 'Victoria Chan', + 'Dominika Mullen', + 'Heath Denton', + 'Lilith Hamilton', + 'Aisling Bailey', + 'Maizie Love', + 'Nathanial Franco', + 'Charmaine Bernard', + 'Sohail Downes', + 'Rabia Gomez', + 'Brendan Brennan', + 'Shannen Atherton', + 'Esa Villarreal', + 'Kayla Wynn', + 'Gladys Hardy', + 'Laaibah Rogers', + 'Zishan Randolph', + 'Connor Connolly', + 'Arabella Wooten', + 'Edna Floyd', +] +const shuffle = (arr) => { + let i = arr.length + let j, tmp + while (--i > 0) { + j = Math.floor(Math.random() * (i + 1)) + tmp = arr[j] + arr[j] = arr[i] + arr[i] = tmp + } + return arr +} +const getRandomList = (names) => + shuffle(names).slice(0, Math.floor(Math.random() * (names.length - 10) + 10)) +const getExpected = (list) => + list + .map((n) => + n + .split(' ') + .reverse() + .join(' '), + ) + .sort() + .map((g, i) => `${i + 1}. ${g}`) + .join('\n') + +export const setup = async () => { + const dir = tmpdir() + + // check if already exists and rm? + await mkdir(`${dir}/${name}`) + const randomList = getRandomList(guests) + const decoded = getExpected(randomList) + const encoded = Buffer.from(decoded).toString('base64') + await writeFile(`${dir}/${name}/encoded.txt`, encoded) + await writeFile(`${dir}/${name}/decoded.txt`, decoded) + + return { tmpPath: `${dir}/${name}`, decoded, encoded } +} +const cypherIt = async ({ keyword, newFile, ctx, path, eq }) => { + const scriptPath = join(resolve(), path) + const filename = keyword === "encode" ? "decoded.txt" : "encoded.txt" + await exec(`node ${scriptPath} ${filename} ${keyword} ${newFile ? newFile : ""}`, { + cwd: ctx.tmpPath, + }) + const newFileName = newFile || (keyword === "encode" ? "cypher.txt" : "clear.txt") + const out = await readFile(`${ctx.tmpPath}/${newFileName}`, 'utf8').catch((err) => + err.code === 'ENOENT' ? 'output file not found' : err, + ) + await exec(`rm ${newFileName}`, { cwd: ctx.tmpPath }) + return eq(out, keyword === "encode" ? ctx.encoded : ctx.decoded) +} + +tests.push(async ({ path, eq, ctx }) => { + return cypherIt({ + path, + eq, + ctx, + keyword: 'encode', + }) +}) + +tests.push(async ({ path, eq, ctx }) => { + return cypherIt({ + path, + eq, + ctx, + keyword: 'decode', + }) +}) + +tests.push(async ({ path, eq, ctx }) => { + return cypherIt({ + path, + eq, + ctx, + keyword: 'encode', + newFile: 'mysecret.txt', + }) +}) + +tests.push(async ({ path, eq, ctx }) => { + return cypherIt({ + path, + eq, + ctx, + keyword: 'decode', + newFile: 'pandora.txt', + }) +}) + +Object.freeze(tests) diff --git a/subjects/tell-it-cypher/README.md b/subjects/tell-it-cypher/README.md new file mode 100644 index 000000000..646b649dc --- /dev/null +++ b/subjects/tell-it-cypher/README.md @@ -0,0 +1,18 @@ +## tell-it-cypher + +### Instructions + +FINALLY, you got the names. +But you could forget it... loose it... How could you write it without puting the surprise in danger?! + +Create a `tell-it-cypher.mjs` script that: +- Takes a file as first argument +- Takes one of these keywords as second argument: + - `encode`: convert your file from `utf8` to `base64`, then save the result in a `cypher.txt` file. + - `decode`: convert your file from `base64` to `utf8`, then save the result in a `clear.txt` file. +- Could take a string as third argument and use it as the new file name. Extension must be precised. + +### Notions + +- [Node buffer: `.from()`](https://nodejs.org/docs/latest/api/buffer.html#buffer_static_method_buffer_from_string_encoding) +- [Node buffer: `.toString()`](https://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end)