Files
metrics/tests/mocks/index.mjs
2022-01-14 00:13:38 -05:00

151 lines
4.2 KiB
JavaScript

//Imports
import fs from "fs/promises"
import axios from "axios"
import faker from "faker"
import paths from "path"
import rss from "rss-parser"
import urls from "url"
//Mocked state
let mocked = false
//Mocking
export default async function({graphql, rest}) {
//Check if already mocked
if (mocked)
return {graphql, rest}
mocked = true
console.debug("metrics/compute/mocks > mocking")
//Load mocks
const __mocks = paths.join(paths.dirname(urls.fileURLToPath(import.meta.url)))
const mock = async ({directory, mocks}) => {
for (const entry of await fs.readdir(directory)) {
if ((await fs.lstat(paths.join(directory, entry))).isDirectory()) {
if (!mocks[entry])
mocks[entry] = {}
await mock({directory:paths.join(directory, entry), mocks:mocks[entry]})
}
else
mocks[entry.replace(/[.]mjs$/, "")] = (await import(urls.pathToFileURL(paths.join(directory, entry)).href)).default
}
return mocks
}
const mocks = await mock({directory:paths.join(__mocks, "api"), mocks:{}})
//GraphQL API mocking
{
//Unmocked
console.debug("metrics/compute/mocks > mocking graphql api")
const unmocked = graphql
//Mocked
graphql = new Proxy(unmocked, {
apply(target, that, args) {
//Arguments
const [query] = args
const login = query.match(/login: "(?<login>.*?)"/)?.groups?.login ?? faker.internet.userName()
//Search for mocked query
for (const mocked of Object.keys(mocks.github.graphql)) {
if (new RegExp(`^query ${mocked.replace(/([.]\w)/g, (_, g) => g.toLocaleUpperCase().substring(1)).replace(/^(\w)/g, (_, g) => g.toLocaleUpperCase())} `).test(query))
return mocks.github.graphql[mocked]({faker, query, login})
}
//Unmocked call
return target(...args)
},
})
}
//Rest API mocking
{
//Unmocked
console.debug("metrics/compute/mocks > mocking rest api")
const unmocked = {}
//Mocked
const mocker = ({path = "rest", mocks, mocked}) => {
for (const [key, value] of Object.entries(mocks)) {
console.debug(`metrics/compute/mocks > mocking rest api > mocking ${path}.${key}`)
if (typeof value === "function") {
unmocked[path] = value
mocked[key] = new Proxy(unmocked[path], {apply:value.bind(null, {faker})})
}
else
mocker({path:`${path}.${key}`, mocks:mocks[key], mocked:mocked[key]})
}
}
mocker({mocks:mocks.github.rest, mocked:rest})
}
//Axios mocking
{
//Unmocked
console.debug("metrics/compute/mocks > mocking axios")
const unmocked = {get:axios.get, post:axios.post}
//Mocked post requests
axios.post = new Proxy(unmocked.post, {
apply(target, that, args) {
//Arguments
const [url, body] = args
//Search for mocked request
for (const service of Object.keys(mocks.axios.post)) {
const mocked = mocks.axios.post[service]({faker, url, body})
if (mocked)
return mocked
}
//Unmocked call
return target(...args)
},
})
//Mocked get requests
axios.get = new Proxy(unmocked.get, {
apply(target, that, args) {
//Arguments
const [url, options] = args
//Search for mocked request
for (const service of Object.keys(mocks.axios.get)) {
const mocked = mocks.axios.get[service]({faker, url, options})
if (mocked)
return mocked
}
//Unmocked call
return target(...args)
},
})
}
//RSS mocking
{
//Unmocked
console.debug("metrics/compute/mocks > mocking rss-parser")
//Mock rss feed
rss.prototype.parseURL = function(url) {
console.debug(`metrics/compute/mocks > mocking rss feed result > ${url}`)
return ({
items:new Array(30).fill(null).map(_ => ({
title:faker.lorem.sentence(),
link:faker.internet.url(),
content:faker.lorem.paragraphs(),
contentSnippet:faker.lorem.paragraph(),
isoDate:faker.date.recent(),
})),
title:faker.lorem.words(),
description:faker.lorem.paragraph(),
link:url,
})
}
}
//Return mocked elements
return {graphql, rest}
}