-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
39 changed files
with
592 additions
and
287 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { describe, it, expect } from "vitest"; | ||
import { mock } from "../lib"; | ||
import { findProvince } from "../lib/random/address/testUtil"; | ||
|
||
describe("地址", () => { | ||
it("省份", () => { | ||
const obj = mock({ | ||
from: "@province", | ||
}); | ||
const from = obj.from as string; | ||
expect(findProvince(from)).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,43 @@ | ||
import { describe, it, expect } from "vitest"; | ||
import { mock } from "../lib"; | ||
|
||
// const { mock } = require("@linzb93/mock"); | ||
describe("数字", () => { | ||
it("小于10的整数", () => { | ||
const obj = mock({ | ||
age: "@integer(1,10)", | ||
}); | ||
expect(Number.isInteger(obj.age)).toBeTruthy(); | ||
expect(obj.age).toBeLessThan(10); | ||
}); | ||
it("浮点数", () => { | ||
const obj = mock({ | ||
money: "@float(10,140, 2, 4)", | ||
}); | ||
expect(Number(obj.money)).not.toBeNaN(); | ||
expect(Number(obj.money)).not.toBe(parseInt(obj.money.toString())); | ||
}); | ||
}); | ||
|
||
describe("布尔值", () => { | ||
it("对或错", () => { | ||
const obj = mock({ | ||
isStudent: "@boolean", | ||
}); | ||
expect(obj.isStudent === true || obj.isStudent === false).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
describe.todo("姓名", () => { | ||
// const map = ["李小明", "张三", "李四", "王五"]; | ||
// it("无筛选", () => { | ||
// expect(map.includes(mock({ name: "@cname" }).name)).toBeTruthy(); | ||
// }); | ||
// it("选一个姓", () => { | ||
// expect( | ||
// ["李小明", "李四"].includes(mock({ name: "@cname(李)" }).name) | ||
// ).toBeTruthy(); | ||
// }); | ||
// it("选一个姓,两个字的名字", () => { | ||
// expect(mock({ name: "@cname(李,2)" })).toEqual({ name: "李四" }); | ||
// }); | ||
describe("字符", () => { | ||
it("小写", () => { | ||
const obj = mock({ | ||
char: "@char", | ||
}); | ||
expect(obj.char).toMatch(/^[a-z]$/); | ||
}); | ||
it("字符串", () => { | ||
const obj = mock({ | ||
name: "@string(4,9)", | ||
}); | ||
expect(obj.name).toMatch(/^[a-z]{4,9}$/); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,78 @@ | ||
import use, { database } from "./use"; | ||
import cname from "../random/name/cname"; | ||
import province from "../random/name/province"; | ||
import city from "../random/name/city"; | ||
import county from "../random/name/county"; | ||
import { database } from "./use"; | ||
import { BasicType } from "../types"; | ||
|
||
export default function (template: any) { | ||
function parseFunctionCall(data: string | number) { | ||
const callString = data.toString(); | ||
// 使用正则表达式匹配函数名称和参数(可选) | ||
const regex = /^\s*@(\w+)\s*(?:\((.*)\))?\s*$/; | ||
const match = callString.match(regex); | ||
|
||
if (!match) { | ||
throw new Error("Invalid function call format"); | ||
} | ||
|
||
// 第一个捕获组是函数名称,第二个捕获组是参数字符串(可选) | ||
const functionName = match[1]; | ||
let args: BasicType[] = []; | ||
|
||
if (match[2]) { | ||
// 如果存在参数字符串,则处理参数 | ||
args = match[2] | ||
.split(",") | ||
.map((arg) => getParams(arg.trim().replace(/['"]+/g, ""))); | ||
} | ||
|
||
// 返回结果对象 | ||
return { fn: functionName, args }; | ||
} | ||
type Result<T> = { [K in keyof T]: string | number | boolean }; | ||
|
||
export default function <T extends Record<string, any>>( | ||
template: T | ||
): Result<T> { | ||
return Object.keys(template).reduce((obj, key) => { | ||
// if (key.includes('|') && Array.isArray(template[key])) { | ||
// const index = key.indexOf('|'); | ||
// const length = Number(key.slice(index + 1)); | ||
|
||
// } | ||
const matchWrap = template[key].slice(1); | ||
const match = matchWrap.match(/^(\w+)(\((\S+)\))?$/); | ||
if (match) { | ||
const args = match[3] ? match[3].split(",") : []; | ||
return { | ||
...obj, | ||
[key]: database[match[1]](...getParams(args)), | ||
}; | ||
const value = template[key]; | ||
if (typeof value !== "string") { | ||
return obj; | ||
} | ||
|
||
const { fn, args } = parseFunctionCall(value); | ||
return { | ||
...obj, | ||
[key]: database[match[1]](), | ||
[key]: database[fn](...args), | ||
}; | ||
}, {}); | ||
}, {} as Result<T>); | ||
} | ||
|
||
function getParams(args: string[]) { | ||
return args.map((arg) => { | ||
if (arg === "true") { | ||
return true; | ||
} | ||
if (arg === "false") { | ||
return false; | ||
} | ||
if (parseInt(arg) === Number(arg)) { | ||
return Number(arg); | ||
} | ||
return arg; | ||
}); | ||
/** | ||
* 将字符串中的boolean值和数字转换成对应类型 | ||
* @param {string[]} arg - 待转换的参数列表 | ||
* @returns | ||
*/ | ||
function getParams(arg: string): BasicType { | ||
if (arg === "true") { | ||
return true; | ||
} | ||
if (arg === "false") { | ||
return false; | ||
} | ||
if (!isNaN(Number(arg))) { | ||
return Number(arg); | ||
} | ||
return arg; | ||
} | ||
|
||
/*** */ | ||
function transformObject<T extends { [K in keyof T]: string }>(obj: T): T { | ||
// 这里可以添加一些转换逻辑,但最终返回的是相同的对象 | ||
return obj; | ||
} | ||
|
||
// 示例调用 | ||
const inputObject = { | ||
name: "Kimi", | ||
age: "30", | ||
country: "Moon", | ||
}; | ||
|
||
const outputObject = transformObject(inputObject); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,16 @@ | ||
type PluginType = (value: string, length: number) => string; | ||
import type { BasicType } from "../types"; | ||
|
||
type PluginType = (...args: any[]) => BasicType; | ||
export const database: { | ||
[key: string]: PluginType; | ||
} = {}; | ||
export default function (name: string, plugin: PluginType) { | ||
database[name] = plugin; | ||
|
||
interface MockPlugin { | ||
name: string; | ||
serve: PluginType; | ||
} | ||
|
||
export default function (plugin: MockPlugin) { | ||
const { name, serve } = plugin; | ||
database[name] = serve; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,24 @@ | ||
import * as utils from "./shared"; | ||
import use from "./core/use"; | ||
import mock from "./core"; | ||
import integer from "./random/basic/integer"; | ||
import char from "./random/basic/char"; | ||
import mockString from "./random/basic/string"; | ||
import mockBoolean from "./random/basic/boolean"; | ||
import float from "./random/basic/float"; | ||
import province from "./random/address/province"; | ||
|
||
/** | ||
* 基础部分 | ||
*/ | ||
use(integer); | ||
use(mockBoolean); | ||
use(char); | ||
use(mockString); | ||
use(float); | ||
/** | ||
* 地址 | ||
*/ | ||
use(province); | ||
|
||
export { utils, use, mock }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,57 @@ | ||
import addrData from "./address_ch.json"; | ||
import { sample } from '../../shared'; | ||
import addrData from "./dict.json"; | ||
import { sample } from "lodash-es"; | ||
|
||
type Props = keyof typeof addrData; | ||
|
||
/** | ||
* | ||
* @param {Boolean | String} args 是否同时显示完整 | 指定省份下的城市 | ||
* @returns string | ||
* 随机获取城市名称 | ||
*/ | ||
module.exports = (...args:any[]) => { | ||
const isFull = | ||
(args.length === 1 && args[0] === true) || | ||
(args.length === 2 && args[1] === true); | ||
const prefix = typeof args[0] === "string" ? args[0] : ""; | ||
if (prefix) { | ||
// 匹配省份 | ||
const provinceCode = Object.keys(addrData).find( | ||
(code) => addrData[code] === prefix | ||
); | ||
if (!provinceCode) { | ||
// 无法匹配的就返回空字符串 | ||
return ""; | ||
} | ||
const cityList = Object.keys(addrData).filter( | ||
(code) => | ||
code.slice(0, 2) === provinceCode.slice(0, 2) && | ||
code.endsWith("00") && | ||
addrData[code] !== prefix | ||
); | ||
if (isFull) { | ||
return `${prefix}${addrData[sample(cityList)]}`; | ||
} | ||
return addrData[sample(cityList)]; | ||
} | ||
const cityCodes = Object.keys(addrData).filter( | ||
(code) => code.endsWith("00") && code.slice(2, 4) !== "00" | ||
); | ||
const cityCode = sample(cityCodes); | ||
const cityName = addrData[cityCode]; | ||
if (isFull) { | ||
const provinceCode = cityCode.toString().replace(/\d{4}$/, "0000"); | ||
const provinceName = addrData[provinceCode]; | ||
return `${provinceName}${cityName}`; | ||
} | ||
export default { | ||
name: "city", | ||
/** | ||
* @param {boolean} showAll - 是否显示完整地址 | ||
* @param {string} prefix - 筛选某个省、自治区、直辖市下的城市 | ||
* @returns {string} | ||
*/ | ||
serve: (showAll: boolean, prefix: string) => { | ||
const cityName = ""; | ||
// 如果prefix不为空,则搜索省份的名字,获取前2位,找到所有code前两位相同的城市。 | ||
|
||
// const isFull = | ||
// (args.length === 1 && args[0] === true) || | ||
// (args.length === 2 && args[1] === true); | ||
// const prefix = typeof args[0] === "string" ? args[0] : ""; | ||
// if (prefix) { | ||
// // 匹配省份 | ||
// const provinceCode = Object.keys(addrData).find( | ||
// (code) => addrData[code] === prefix | ||
// ); | ||
// if (!provinceCode) { | ||
// // 无法匹配的就返回空字符串 | ||
// return ""; | ||
// } | ||
// const cityList = Object.keys(addrData).filter( | ||
// (code) => | ||
// code.slice(0, 2) === provinceCode.slice(0, 2) && | ||
// code.endsWith("00") && | ||
// addrData[code] !== prefix | ||
// ); | ||
// if (isFull) { | ||
// return `${prefix}${addrData[sample(cityList)]}`; | ||
// } | ||
// return addrData[sample(cityList)]; | ||
// } | ||
// const cityCodes = Object.keys(addrData).filter( | ||
// (code) => code.endsWith("00") && code.slice(2, 4) !== "00" | ||
// ); | ||
// const cityCode = sample(cityCodes); | ||
// const cityName = addrData[cityCode]; | ||
// if (isFull) { | ||
// const provinceCode = cityCode.toString().replace(/\d{4}$/, "0000"); | ||
// const provinceName = addrData[provinceCode]; | ||
// return `${provinceName}${cityName}`; | ||
// } | ||
|
||
return cityName; | ||
return cityName; | ||
}, | ||
}; |
Oops, something went wrong.