Token导航 LogoToken导航

Agent Skill · 前端设计

mock-data(模拟数据)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

mock-data 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证为 MIT,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 8,138。

总安装 312周安装 13GitHub Stars 20下载 104核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:mock-data(模拟数据)
来源仓库:https://github.com/sgcarstrends/sgcarstrends
仓库路径:skills/mock-data
安装命令:
npx skills add https://github.com/sgcarstrends/sgcarstrends --skill mock-data
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/sgcarstrends/sgcarstrends --skill mock-data

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

用于辅助前端页面、组件、样式和交互逻辑的开发与维护,适合生成或审查 React、Vue、CSS 等相关代码。适用于前端组件结构整理、布局问题定位和性能优化等开发场景。通过 GitHub 仓库安装,使用 npx skills add 命令添加技能,需结合项目现有设计系统和路由使用。

涉及页面改动时应配合本地预览和构建检查确认视觉效果,避免生成孤立片段。mock-data 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/mock-data

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/sgcarstrends/sgcarstrends --skill mock-data;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

mock-data 怎么安装?

在终端执行 npx skills add https://github.com/sgcarstrends/sgcarstrends --skill mock-data。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

mock-data 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

mock-data 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

mock-data 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

mock-data 用的人多吗?

公开数据是累计安装 312 次,近一周安装 13 次,下载 104 次,GitHub 20 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

mock-data 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
mock-data

模拟数据 · 本页

31220需要联网MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Mock Data Generation Skill

This skill helps you generate realistic mock data for testing, development, and seeding purposes.

When to Use This Skill

  • Creating test fixtures for unit/integration tests
  • Seeding test databases
  • Mocking API responses
  • Generating sample data for development
  • Creating realistic data for E2E tests
  • Populating staging environments
  • Testing edge cases with specific data patterns

Tools & Libraries

Faker.js

Primary library for generating realistic fake data:

# Install Faker
pnpm add -D @faker-js/faker

Features:

  • Person data (names, emails, phone numbers)
  • Addresses and locations
  • Dates and times
  • Commerce data (products, prices)
  • Vehicle data
  • Lorem ipsum text
  • Custom locales (including Singapore)

Basic Mock Data Patterns

Simple Factories

// apps/api/__tests__/factories/car.factory.ts
import { faker } from "@faker-js/faker";

export const createMockCar = (overrides = {}) => ({
  id: faker.string.uuid(),
  make: faker.vehicle.manufacturer(),
  model: faker.vehicle.model(),
  vehicleType: faker.helpers.arrayElement(["Passenger Car", "Goods Vehicle"]),
  fuelType: faker.helpers.arrayElement(["Petrol", "Diesel", "Electric", "Hybrid"]),
  month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
  number: faker.number.int({ min: 1, max: 1000 }),
  ...overrides,
});

// Usage
const car = createMockCar({ make: "Toyota", model: "Corolla" });

Factory Functions

// apps/api/__tests__/factories/index.ts
import { faker } from "@faker-js/faker";

export const CarFactory = {
  build: (overrides = {}) => ({
    id: faker.string.uuid(),
    make: faker.vehicle.manufacturer(),
    model: faker.vehicle.model(),
    month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
    number: faker.number.int({ min: 1, max: 1000 }),
    ...overrides,
  }),

  buildMany: (count: number, overrides = {}) => {
    return Array.from({ length: count }, () => CarFactory.build(overrides));
  },

  buildToyota: () => CarFactory.build({ make: "Toyota" }),

  buildElectric: () => CarFactory.build({ fuelType: "Electric" }),
};

export const COEFactory = {
  build: (overrides = {}) => ({
    id: faker.string.uuid(),
    month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
    biddingNo: faker.number.int({ min: 1, max: 24 }),
    vehicleClass: faker.helpers.arrayElement(["A", "B", "C", "D", "E"]),
    quota: faker.number.int({ min: 100, max: 5000 }),
    bidsReceived: faker.number.int({ min: 1000, max: 10000 }),
    premiumAmount: faker.number.int({ min: 50000, max: 150000 }),
    ...overrides,
  }),

  buildMany: (count: number, overrides = {}) => {
    return Array.from({ length: count }, () => COEFactory.build(overrides));
  },

  buildCategoryA: () => COEFactory.build({ vehicleClass: "A" }),
};

export const BlogPostFactory = {
  build: (overrides = {}) => ({
    id: faker.string.uuid(),
    title: faker.lorem.sentence(),
    slug: faker.helpers.slugify(faker.lorem.sentence()),
    content: faker.lorem.paragraphs(3),
    excerpt: faker.lorem.paragraph(),
    publishedAt: faker.date.recent({ days: 30 }),
    authorId: faker.string.uuid(),
    ...overrides,
  }),

  buildMany: (count: number, overrides = {}) => {
    return Array.from({ length: count }, () => BlogPostFactory.build(overrides));
  },

  buildPublished: () => BlogPostFactory.build({
    publishedAt: faker.date.past(),
  }),

  buildDraft: () => BlogPostFactory.build({
    publishedAt: null,
  }),
};

Advanced Factories

Class-Based Factories

// apps/api/__tests__/factories/base.factory.ts
import { faker } from "@faker-js/faker";

export abstract class BaseFactory<T> {
  abstract build(overrides?: Partial<T>): T;

  buildMany(count: number, overrides?: Partial<T>): T[] {
    return Array.from({ length: count }, () => this.build(overrides));
  }

  buildList(items: Partial<T>[]): T[] {
    return items.map((item) => this.build(item));
  }
}

// Specific factory
export class CarFactory extends BaseFactory<Car> {
  build(overrides: Partial<Car> = {}): Car {
    return {
      id: faker.string.uuid(),
      make: faker.vehicle.manufacturer(),
      model: faker.vehicle.model(),
      month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
      number: faker.number.int({ min: 1, max: 1000 }),
      ...overrides,
    };
  }

  buildToyota(): Car {
    return this.build({ make: "Toyota" });
  }

  buildWithHighRegistrations(): Car {
    return this.build({ number: faker.number.int({ min: 500, max: 1000 }) });
  }
}

// Usage
const carFactory = new CarFactory();
const cars = carFactory.buildMany(10);
const toyota = carFactory.buildToyota();

Sequence Factories

// apps/api/__tests__/factories/sequence.ts
import { faker } from "@faker-js/faker";

let sequenceCounters: Record<string, number> = {};

export const sequence = (name: string, fn: (n: number) => any) => {
  if (!sequenceCounters[name]) {
    sequenceCounters[name] = 0;
  }
  sequenceCounters[name]++;
  return fn(sequenceCounters[name]);
};

export const resetSequences = () => {
  sequenceCounters = {};
};

// Usage
export const UserFactory = {
  build: (overrides = {}) => ({
    id: sequence("user", (n) => `user-${n}`),
    email: sequence("email", (n) => `user${n}@example.com`),
    name: faker.person.fullName(),
    ...overrides,
  }),
};

// In tests
beforeEach(() => {
  resetSequences();
});

const user1 = UserFactory.build(); // { id: "user-1", email: "user1@example.com" }
const user2 = UserFactory.build(); // { id: "user-2", email: "user2@example.com" }

Fixtures

Static Fixtures

// apps/api/__tests__/fixtures/cars.ts
export const toyotaCorollaFixture = {
  make: "Toyota",
  model: "Corolla",
  month: "2024-01",
  number: 150,
};

export const hondaCivicFixture = {
  make: "Honda",
  model: "Civic",
  month: "2024-01",
  number: 120,
};

export const popularCarsFixture = [
  toyotaCorollaFixture,
  hondaCivicFixture,
  {
    make: "BMW",
    model: "3 Series",
    month: "2024-01",
    number: 80,
  },
];

// Usage in tests
import { toyotaCorollaFixture } from "./fixtures/cars";

it("should process Toyota Corolla data", () => {
  const result = processCarData(toyotaCorollaFixture);
  expect(result.make).toBe("Toyota");
});

JSON Fixtures

// apps/api/__tests__/fixtures/cars.json
[
  {
    "make": "Toyota",
    "model": "Corolla",
    "month": "2024-01",
    "number": 150
  },
  {
    "make": "Honda",
    "model": "Civic",
    "month": "2024-01",
    "number": 120
  }
]

// Load in tests
import carsFixture from "./fixtures/cars.json";

it("should load fixture data", () => {
  expect(carsFixture).toHaveLength(2);
  expect(carsFixture[0].make).toBe("Toyota");
});

Dynamic Fixtures

// apps/api/__tests__/fixtures/dynamic.ts
import { faker } from "@faker-js/faker";

export const generateCarFixtures = (count: number, month: string) => {
  return Array.from({ length: count }, () => ({
    make: faker.vehicle.manufacturer(),
    model: faker.vehicle.model(),
    month,
    number: faker.number.int({ min: 1, max: 500 }),
  }));
};

// Usage
const januaryCars = generateCarFixtures(100, "2024-01");
const februaryCars = generateCarFixtures(100, "2024-02");

Singapore-Specific Mock Data

Singapore Locales

// apps/api/__tests__/factories/singapore.ts
import { faker } from "@faker-js/faker";
import { fakerEN_SG } from "@faker-js/faker";

// Use Singapore locale
faker.setDefaultLocale("en_SG");

export const SingaporeAddressFactory = {
  build: () => ({
    street: faker.location.street(),
    postalCode: faker.location.zipCode("######"), // 6-digit postal code
    country: "Singapore",
  }),
};

export const SingaporePhoneFactory = {
  build: () => ({
    mobile: `+65 ${faker.helpers.arrayElement(["8", "9"])}${faker.string.numeric(7)}`,
    home: `+65 6${faker.string.numeric(7)}`,
  }),
};

// Singapore car makes (popular in Singapore)
export const SingaporeCarMakes = [
  "Toyota",
  "Honda",
  "Mercedes-Benz",
  "BMW",
  "Mazda",
  "Hyundai",
  "Kia",
  "Nissan",
  "Volkswagen",
  "Audi",
];

export const SingaporeCarFactory = {
  build: (overrides = {}) => ({
    make: faker.helpers.arrayElement(SingaporeCarMakes),
    model: faker.vehicle.model(),
    month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
    number: faker.number.int({ min: 1, max: 500 }),
    ...overrides,
  }),
};

COE Categories

// apps/api/__tests__/factories/coe.ts
export const COECategories = {
  A: "Cars up to 1600cc & 97kW",
  B: "Cars above 1600cc or 97kW",
  C: "Goods Vehicles & Buses",
  D: "Motorcycles",
  E: "Open Category",
};

export const COEFactory = {
  build: (overrides = {}) => {
    const category = faker.helpers.arrayElement(["A", "B", "C", "D", "E"]);

    return {
      month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
      biddingNo: faker.number.int({ min: 1, max: 24 }),
      vehicleClass: category,
      quota: faker.number.int({ min: 100, max: 5000 }),
      bidsReceived: faker.number.int({ min: 1000, max: 10000 }),
      premiumAmount: faker.number.int({ min: 30000, max: 150000 }),
      ...overrides,
    };
  },

  buildRealistic: () => {
    const category = faker.helpers.arrayElement(["A", "B"]) as "A" | "B";
    const basePrice = category === "A" ? 60000 : 90000;

    return COEFactory.build({
      vehicleClass: category,
      premiumAmount: basePrice + faker.number.int({ min: -10000, max: 30000 }),
    });
  },
};

Database Seeding

Seed Scripts

// apps/api/scripts/seed.ts
import { db } from "../src/config/database";
import { cars, coe, posts } from "@sgcarstrends/database/schema";
import { CarFactory, COEFactory, BlogPostFactory } from "../__tests__/factories";

async function seed() {
  console.log("Seeding database...");

  // Clear existing data
  await db.delete(cars);
  await db.delete(coe);
  await db.delete(posts);

  // Seed cars
  const carData = CarFactory.buildMany(1000);
  await db.insert(cars).values(carData);
  console.log("✓ Seeded 1000 cars");

  // Seed COE
  const coeData = COEFactory.buildMany(240); // 24 bidding rounds * 10 months
  await db.insert(coe).values(coeData);
  console.log("✓ Seeded 240 COE records");

  // Seed blog posts
  const postData = BlogPostFactory.buildMany(50);
  await db.insert(posts).values(postData);
  console.log("✓ Seeded 50 blog posts");

  console.log("Seeding complete!");
}

seed().catch(console.error);

Environment-Specific Seeding

// apps/api/scripts/seed-env.ts
import { db } from "../src/config/database";
import { CarFactory, COEFactory } from "../__tests__/factories";

async function seedForEnvironment(env: string) {
  const counts = {
    development: { cars: 1000, coe: 240 },
    test: { cars: 100, coe: 24 },
    staging: { cars: 10000, coe: 1000 },
  };

  const config = counts[env as keyof typeof counts] || counts.development;

  console.log(`Seeding ${env} environment...`);

  await db.insert(cars).values(CarFactory.buildMany(config.cars));
  await db.insert(coe).values(COEFactory.buildMany(config.coe));

  console.log(`✓ Seeded ${config.cars} cars and ${config.coe} COE records`);
}

const env = process.env.NODE_ENV || "development";
seedForEnvironment(env).catch(console.error);

API Response Mocking

Mock API Responses

// apps/api/__tests__/mocks/api-responses.ts
export const mockLTACarResponse = {
  records: [
    {
      month: "2024-01",
      make: "TOYOTA",
      fuel_type: "Petrol",
      vehicle_type: "Passenger Car",
      number: 150,
    },
    {
      month: "2024-01",
      make: "HONDA",
      fuel_type: "Petrol",
      vehicle_type: "Passenger Car",
      number: 120,
    },
  ],
};

export const mockLTACOEResponse = {
  records: [
    {
      month: "2024-01",
      bidding_no: "1",
      vehicle_class: "A",
      quota: 1000,
      bids_received: 5000,
      premium: 65000,
    },
  ],
};

export const mockErrorResponse = {
  error: {
    code: "INTERNAL_ERROR",
    message: "An error occurred",
  },
};

// Usage in tests
import { mockLTACarResponse } from "./mocks/api-responses";

vi.spyOn(global, "fetch").mockResolvedValue({
  ok: true,
  json: async () => mockLTACarResponse,
} as Response);

Dynamic Mock Generators

// apps/api/__tests__/mocks/generators.ts
import { faker } from "@faker-js/faker";

export const generateMockLTAResponse = (recordCount: number) => ({
  records: Array.from({ length: recordCount }, () => ({
    month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
    make: faker.vehicle.manufacturer().toUpperCase(),
    fuel_type: faker.helpers.arrayElement(["Petrol", "Diesel", "Electric"]),
    vehicle_type: "Passenger Car",
    number: faker.number.int({ min: 1, max: 500 }),
  })),
});

// Usage
const response = generateMockLTAResponse(100);

Testing with Mock Data

Using Factories in Tests

// apps/api/__tests__/routes/cars.test.ts
import { describe, it, expect, beforeEach } from "vitest";
import { db } from "../../src/config/database";
import { CarFactory } from "../factories";
import app from "../../src/index";

describe("GET /api/v1/cars/makes", () => {
  beforeEach(async () => {
    // Seed with factory data
    const cars = CarFactory.buildMany(100);
    await db.insert(cars).values(cars);
  });

  it("should return list of makes", async () => {
    const res = await app.request("/api/v1/cars/makes");

    expect(res.status).toBe(200);
    expect(await res.json()).toHaveLength(expect.any(Number));
  });
});

Using Fixtures in Tests

// apps/api/__tests__/services/coe.test.ts
import { describe, it, expect } from "vitest";
import { calculateCOEPremium } from "../../src/services/coe";
import { mockCOEData } from "../fixtures/coe";

describe("calculateCOEPremium", () => {
  it("should calculate premium correctly", () => {
    const result = calculateCOEPremium(mockCOEData);

    expect(result).toBeGreaterThan(0);
  });
});

Best Practices

1. Keep Factories Simple

// ❌ Too complex
export const ComplexCarFactory = {
  build: async (overrides = {}) => {
    const make = await fetchMakeFromDatabase(); // Don't do async operations
    const model = complexCalculation(make); // Don't do complex logic
    return { make, model, ...overrides };
  },
};

// ✅ Simple and synchronous
export const SimpleCarFactory = {
  build: (overrides = {}) => ({
    make: faker.vehicle.manufacturer(),
    model: faker.vehicle.model(),
    ...overrides,
  }),
};

2. Use Realistic Data

// ❌ Unrealistic test data
const car = { make: "test", model: "test", number: 99999999 };

// ✅ Realistic test data
const car = CarFactory.build({
  make: "Toyota",
  model: "Corolla",
  number: 150,
});

3. Don't Over-Mock

// ❌ Mocking everything
vi.spyOn(db, "insert").mockResolvedValue([]);
vi.spyOn(redis, "get").mockResolvedValue(null);
vi.spyOn(fetch, "fetch").mockResolvedValue({});

// ✅ Only mock external dependencies
vi.spyOn(fetch, "fetch").mockResolvedValue(mockResponse);
// Let db and redis work normally in integration tests

4. Isolate Test Data

// ❌ Shared mutable state
const sharedCar = CarFactory.build();

it("test 1", () => {
  sharedCar.number = 100; // Mutates shared state
});

it("test 2", () => {
  expect(sharedCar.number).toBe(100); // Depends on test 1
});

// ✅ Independent test data
it("test 1", () => {
  const car = CarFactory.build();
  car.number = 100;
});

it("test 2", () => {
  const car = CarFactory.build();
  expect(car.number).toBeGreaterThan(0);
});

Troubleshooting

Faker Generating Same Data

// Issue: Faker generates same data in tests
// Solution: Use unique identifiers or sequences

import { sequence } from "./sequence";

const user1 = UserFactory.build(); // Same email
const user2 = UserFactory.build(); // Same email

// Fix with sequence
export const UserFactory = {
  build: (overrides = {}) => ({
    email: sequence("email", (n) => `user${n}@example.com`),
    ...overrides,
  }),
};

Factory Data Not Matching Schema

// Issue: Factory generates invalid data
// Solution: Use Zod schema validation in factory

import { z } from "zod";

const carSchema = z.object({
  make: z.string().min(1),
  model: z.string().min(1),
  month: z.string().regex(/^\d{4}-\d{2}$/),
  number: z.number().int().min(0),
});

export const CarFactory = {
  build: (overrides = {}) => {
    const data = {
      make: faker.vehicle.manufacturer(),
      model: faker.vehicle.model(),
      month: faker.date.recent({ days: 365 }).toISOString().slice(0, 7),
      number: faker.number.int({ min: 1, max: 1000 }),
      ...overrides,
    };

    return carSchema.parse(data); // Validates before returning
  },
};

References

- apps/api/scripts/seed.ts - Database seeding - Root CLAUDE.md - Testing guidelines

Best Practices Summary

  1. Use Factories: Create reusable factory functions for common entities
  2. Realistic Data: Generate data that resembles production
  3. Fixtures for Static: Use fixtures for known test cases
  4. Factories for Dynamic: Use factories for varied test scenarios
  5. Isolate Test Data: Each test should have independent data
  6. Seed Databases: Use factories to seed dev/test databases
  7. Singapore-Specific: Use appropriate locales and realistic values
  8. Keep Simple: Factories should be synchronous and straightforward

平台分布

Claude Code

28.04%
按下载量换算29

Antigravity

24.33%
按下载量换算25

windsurf

19.32%
按下载量换算20

Gemini CLI

11.36%
按下载量换算12

OpenCode

8.67%
按下载量换算9

Codex

3.51%
按下载量换算4

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills