Git Product home page Git Product logo

intermock's Introduction

intermock Build Status

Mocking library to create mock objects and JSON for TypeScript interfaces via Faker.

This is not an officially supported Google product.

Installation

npm install intermock

CLI

Intermock exposes a CLI, which is the recommended way to use the tool. The following subsections show an example file, command, and output to demonstrate using the CLI.

Example file

interface Admin extends User {
   adminRecord: AdminRecord;
}

interface Student extends User {
   schoolRecord: SchoolRecord;
}

interface User {
   firstName: string;
   lastName: string;
   username: string;
   emailAddress: string;
}

interface AdminRecord {
   studentsPassedEachYear: number[];
}

interface SchoolRecord {
   startDate: string;
   endDate: string;
   isActive: boolean;
   grades: number[];
}

Example command

node ./node_modules/intermock/build/src/cli/index.js --files ./example-file.ts --interfaces "Admin"

Example output

{
  "Admin": {
    "firstName": "Willa",
    "lastName": "Walker",
    "username": "Shyann_Mante",
    "emailAddress": "[email protected]",
    "adminRecord": {
      "studentsPassedEachYear": [
        80342,
        23404,
        12854,
        74937,
        38185,
        73316
      ]
    }
  },

API Usage

Intermock’s API exports only one function, as seen below:

Function

// Returns an object or string based on `output` property specified in `Options`
mock(options: Options): object|string

Options

export interface Options {
 // Array of file tuples. (filename, data)
 files?: Array<[string, string]>;

 // TypeScript is currently the only supported language
 language?: SupportedLanguage;

 // Specific interfaces to write to output
 interfaces?: string[];

 // Used for testing mode,
 isFixedMode?: boolean;

 // One of object|json|string. Strings have their object's functions
 // stringified.
 output?: OutputType;

 // Should optional properties always be enabled
 isOptionalAlwaysEnabled?: boolean;
}

Type Support

The following TypeScript features are supported:

  • Interfaces
  • Interfaces with properties of primitive types
  • Interfaces with property references to other complex types
  • Interfaces with extensions
  • Unions
  • Type aliases
  • Arrays
  • Namespaces
  • Tuples
  • Mapped types
  • Generics
  • Functions (stringified output!)
  • Optional properties
  • Type imports
  • Specific Faker data types (via JSDoc comment)
    interface Host {
      /** @mockType {internet.ipv6} */
      addr: string;
    }

Building

npm run build

Development

If you want to run the build script and tests after you save a file while developing, run the following command: npm run test-watch

Docs

Developing Docs

To develop documentation run the following commands:

npm run build
npm run docs-serve

Edit the files in docs/ and Webpack's Dev Server should auto-reload when there are changes

Statically Building Docs

To build the docs statically run the following command:

npm run build
npm run docs-build

Contributing

  1. Read all of CONTRIBUTING.md in this repo
  2. Sign the CLA
  3. In a terminal, run npm run ci
  4. Fix any linting, formatting, and/or compiling errors. (Note: Format errors can be fixed by npm run format. DO NOT fix linting errors by disabling the linter on a line and/or block)
  5. Create a Pull Request
  6. Address all comments, if any
  7. If everything looks good after comments are addressed, your PR will be merged!

License

See LICENSE in this repo

intermock's People

Contributors

981377660lmt avatar claabs avatar hasparus avatar ignacioureta avatar kahirokunn avatar mbates avatar petrhanak avatar ryanmcdermott avatar wesleyyee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

intermock's Issues

!mockType is non-standard JSDoc tag (exclamation mark)

Hi @ryanmcdermott 👋

I wanted to ask about the exclamation mark in !mockType.
It wasn't obvious to me why is there "!" instead of usual "@".

I think changing it to "@" would align better with TSDoc and be more familiar for people used to @param (I guess this is the most used JSDoc tag).

I've taken a quick look at AST Viewer with "show internals" flag on.

Instead of looking for "!mockType" with startsWith one could look inside propertySignature.jsDoc[number].tags for tag.tagName.text === "mockType".

Here's the gist with a proof of concept https://gist.github.com/hasparus/b1f78bffb783376a62dcd666de41da60

I you like the idea I'd gladly provide a pull request.

Using `intermock` in tests ?

Hello there and thank you for this great project!

I wanted to use intermock to generate stub data while testing. I tried to run it as:

import {mock} from 'intermock'

describe('generate mocked types', () => {
   it('should generate mocked types', () => {
     const mck = mock({files: [['./types.ts', 'MyType']]})
     console.log(mck)
  }
})

But whenever I run this, mck is empty ({}) - any idea what I'm doing wrong ? There's no error printed to the terminal, so I'm thinking that I'm doing something wrong somewhere 🤔

Support for Mapped Types

export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export type User = {
  email: Scalars['String'];
};

Multiple namespaces result in empty objects too

So first of all this is an amazing idea for a library. I spent a while for something like this so great job.

I noticed these issues:

It seemed that mocks generated from multiple files are not working correctly. I decided to merge all files with my types first and then use the mock function but it turns out that this way it doesn't work either.

For something like this:

runTestCase(
   './src/autogenerated-merged-types.ts',
  {
    interfaces: ['IEvent'],
    isOptionalAlwaysEnabled: true,
  }
)

When I use namespaces:

export namespace AuthStore {
  export enum StatusEnum {
    loggingIn = 'loggingIn',
    registering = 'registering',
    idle = 'idle',
  }

  export interface IUser {
    id: string
    firstName: string
    lastName: string
    email: string
  }
}

export namespace EventsStore {
  export interface IEvent {
    id: string
    title: string
    description: string
    startsAt: string
    capacity: number
    owner: AuthStore.IUser
    attendees: AuthStore.IUser[]
  }
}

This is the result:

{
  IEvent: {
    id: '3923e5ac-dc4e-4697-8dc0-4672a6a3fceb',
    title: 'Voluptas eius sit.',
    description: 'Ipsa enim illum non quia et quod molestiae qui.',
    startsAt: 'cumque voluptatibus ut',
    capacity: 97596,
    owner: {},
    attendees: [ {}, {}, {}, {} ]
  }
}

However when I remove namespaces:

export enum StatusEnum {
  loggingIn = 'loggingIn',
  registering = 'registering',
  idle = 'idle',
}

export interface IUser {
  id: string
  firstName: string
  lastName: string
  email: string
}

export interface IEvent {
  id: string
  title: string
  description: string
  startsAt: string
  capacity: number
  owner: IUser
  attendees: IUser[]
}

I get this result:

 {
  IEvent: {
    id: '0fc8dff5-d712-4e2f-adbd-7280e02312bc',
    title: 'est dolorem non',
    description: 'Molestiae est beatae quod voluptatum.',
    startsAt: 'officiis enim rerum',
    capacity: 11416,
    owner: {
      id: 'a5aa5c4a-4713-4447-9a2a-e61040821d9a',
      firstName: 'Tracey',
      lastName: 'Graham',
      email: '[email protected]'
    },
    attendees: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object]
    ]
  }
}

So my questions are:

  • is this going to be fixed in the near future? because at this point the library is useless
  • if not do you know at least roughly what causes the problem? maybe I can take a look at it by the end of this year?

Types from tsconfig are not available in node api

Given:

types.ts

interface Test {
  promise: Promise<any>;
}

tsconfig.json

{
  "compilerOptions": {
    "lib": [
      "es2015",    ],
}

and my usage file test.ts

const data = mock({
  files: [
    [
      path.join(__dirname, 'types.ts'),
      fs.readFileSync(path.join(__dirname, 'types.ts'), 'utf-8')
    ],
  ],
  interfaces: ['Test'],
  output: 'object',
});

I would expect the following interface to work, but I get the error:

Type 'Promise' is not specified in the provided files but is required for property: 'promise'. Please include it.

In the docs we see that 'Interfaces with property references to other complex types ' are supported. since Promise is an other complex types I would assume it would work.

Is there some special configuration for including a tsconfig or do we need to import all type dependencies? or how should we handle such cases. We are currently investigating using this lib for mocking in test and dev environments and will need to support many such use cases such as dom types, react component types, etc.

Please advise :)

@mockType can not work well.

I tried to use mockType feature but it won't work well when using @mockType. I found out it should be !mockType instead after I looked into the code base. The fast way to verify this error is to run the following typescript definition on https://google.github.io/intermock/.

But I also found one existing feature PR11 to support @mockType. Maybe because you guys have not republish to npm lol.

the error one

interface Host {
  /** @mockType {internet.ipv6} */
  addr: string;
}

the right one

interface Host {
  /** !mockType {internet.ipv6} */
  addr: string;
}

No way to select json as output format.

The cli does not allow an outputFormat to be specified, so formatOutput() always defaults to the default "object" instead of json.

cli/index.js should have this added to optionDefinitions
{ name: 'outputFormat', alias: 'o', type: String },

with that outputFormat added to the options call to mock()

This feature is absolutely necessary

#58

This feature is absolutely necessary. However, the code has been merged, but it doesn't seem to have been distributed to a new version yet. can you check it?

Trying to mock APIGatewayProxyEvent in aws-lambda types causes unsupported primitive type 168

Hello this project looks interesting, I was trying to use it for generating an APIGatewayProxyEvent.

However I get the following error:

$ intermock --files node_modules/@types/aws-lambda/index.d.ts --interfaces APIGatewayProxyEvent
Unsupported Primitive type 168

The source file is located here:
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/aws-lambda/index.d.ts#L79

I had a look at the type and couldn't figure out what the unsupported part is, it looks like most are the supported ones, but might have missed what is different due to the quite huge object.

Any ideas what 168 means?

Does not support npx

I tried to use intermock with npx and got the following errors:

/Users/istvanfulop/.npm/_npx/63491/bin/intermock: line 1: use strict: command not found
/Users/istvanfulop/.npm/_npx/63491/bin/intermock: line 2: syntax error near unexpected token `exports,'
/Users/istvanfulop/.npm/_npx/63491/bin/intermock: line 2: `Object.defineProperty(exports, "__esModule", { value: true });'

Record is not supported

Got error

error - Error: Type 'Record' is not specified in the provided files but is required for property: '...'. Please include it.

[DOCS] specify supported faker methods

There's currently no documentation for the supported faker methods that can be used to generate data for datatypes that are not yet supported by the mocker ( date, etc...).

support type literal

export type Gender = 'Male' | 'Female';

export interface Human {
   sex: Gender,
   name: string,
   age: number
}

trying to mock Human results in

{
  "Human": {
    "name": "Burnice Jacobs",
    "age": 53610
  }
};

Support Typed Arrays

Error: Type 'Int8Array' is not specified in the provided files but is required for property: 'arr'. Please include it.

Would be awesome if intermock would support Typed Arrays and generate values within each range e.g.

Array<T>
ReadonlyArray<T>
Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array (represented as string for JSON compatibility)
BigInt64Array (represented as string for JSON compatibility)
BigUint64Array (represented as string for JSON compatibility)

e.g.

interface Data {
  str: string
  arr: Int8Array;
}

const arr = [...new Int8Array([127, 0, 0, 1])]

Output

{
  "Data": {
    "str": "voluptatum minima voluptates",
    "arr": [
      127,
      0,
      0,
      1,
    ]
  }
}

Ref: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/globals.d.ts#L94-L106

@mockType for aliases

I am not an expert at typescript, but I am using interfaces as a descriptive tool to describe my application state model. This lib is great.

It would be really useful if you could set `@mockType at an alias level for instance:

type UserId = string /** @mockType {random.uuid} */

interface User {
  userId: UserId
  group: UserId[]
}

// returns

{
   userId: 97896447-4453-4718-990d-1d2a5f38533b,
   group: [ 28939844-74c4-4907-b596-41f1382a2607 ]
}

Currently my Array of string types returns:

{
   userId: 97896447-4453-4718-990d-1d2a5f38533b,
   group: [ {}, {}, {} ]
}

Array of alias values mock as empty objects

File t1.ts

type MyType = string;

interface Data {
    val: MyType;
    arr: MyType[];
}

node build/src/cli/index.js --files t1.ts --interfaces Data -o string

Result:

{
  "Data": {
    "val": "excepturi qui voluptatem",
    "arr": [
      {},
      {},
      {}
    ]
  }
};

Maximum call stack size exceeded

Interfaces with recursive data types throw a 'Maximum call stack size exceeded' error

interface User {
   firstName: string;
   lastName: string;
   username: string;
   emailAddress: string;
   bestFriends: User[];
}

References to objects between files fake as empty objects

File f1.ts:

import Data2 from "./f2";

interface LocalData {
    val: string;
}

interface Data1 {
    val1: Data2;
    val2: LocalData;
}

File f2.ts:

interface Data2 {
    val: string;
}

node build/src/cli/index.js --files f1.ts f2.ts --interfaces Data1 Data2

Results:

{
  Data1: { val1: {}, val2: { val: 'quia dolores quam' } },
  Data2: {
    val: 'Sequi iure nulla reprehenderit impedit in explicabo saepe. Voluptatibus ex quo. Voluptas qui sunt minus.\n' +
      ' \rSed expedita sunt iure pariatur molestiae velit repellendus. Quisquam architecto explicabo quas et numquam. Commodi eos itaque voluptatem quia qui et alias. Tempora ut animi id sint non consequatur et.\n' +
      ' \rNon aut et aut et qui facere nesciunt eos aut. Sunt corrupti harum et commodi quibusdam et placeat voluptas id. Qui voluptas unde. Voluptatem in atque aperiam possimus sit ad minima.'
  }
}

Notice Data1.val1 is {}.

Generic Interface mock as empty object

My ts file is like this:

interface User {
  name: string;
  age: number;
  gender: 'male' | 'female';
}

interface IResponse<T> {
  code: number;
  data: T;
}

export interface UserResponse extends IResponse<User> {}; 

And i got mock data like this:

{
  User: { name: 'Diamond Grant', age: 57103, gender: 'female' },
  IResponse: { code: 14453, data: {} },
  UserResponse: { code: 68883, data: {} }
}

All my generic type result in empty object

Support Relative Imported Interfaces

I have:

import {Bar,Fizz} from './'

interface Foo {
 bar: Bar,
 fizz: Fizz
}

output becomes:

{
  "Foo": {
    bar: {},
    fizz: {}
  }
}

expected:

{
  "Foo": {
    bar: // Bar's mock data ,
    fizz: // Fizz's mock data 
  }
}

Can I open a PR to support this feature ? 😃

Multiple object output

Hi, Currently the web app output a single object per interface. I was thinking it would be more useful if it supports multi-object output like an object array so that users can get mocks as necessary with a single instance.

Suggestions

  • Object array support
  • Simple "copy to clipboard" button to copy the output

Can you please let me know if there is a similar update going on, or else I'm glad to contribute.

Support Date

When I mock data contains Date, intermock throw UnhandledPromiseRejectionWarning: Error: Type 'Date' is not specified in the provided files but is required for property: 'completedDate'. Please include it..

Support for enum arrays

I have:

enum StudentType { FullTime = 0, PartTime = 1, TeacherAssistant = 2 }

interface User { firstName: string; lastName: string; username: string; emailAddress: string; studentTypes: StudentType[] }

output becomes:
{ "Admin": { "firstName": "Libbie", "lastName": "Kuhic", "username": "Forest_Block", "emailAddress": "[email protected]", "studentTypes": [ {}, {}, {} ], "adminRecord": { "studentsPassedEachYear": [ 64163 ] } }, }

expected:
{ "Admin": { "firstName": "Libbie", "lastName": "Kuhic", "username": "Forest_Block", "emailAddress": "[email protected]", "studentTypes": [ 0,1,2 ], "adminRecord": { "studentsPassedEachYear": [ 64163 ] } }, }

Support specifying namespaced types

We are using gRPC-Web and it generates types similar to the following from protobuf definitions:

export namespace Todo {
  export type AsObject = {
    id: string,
    title: string,
    completed: boolean,
  }
}

export namespace GetTodoRequest {
  export type AsObject = {
    id: string,
  }
}

I would like to be able to call the intermock CLI with the option --interfaces "Todo.AsObject" "GetTodoRequest.AsObject".

Currently I'm only able to run --interfaces "AsObject", which only generates a mock for the very last AsObject type that intermock finds, i.e. GetTodoRequest.AsObject.

RFC: Support generating factories

When using mock data in tests I would like to

  1. overwrite partial data (and have type-support for it out of the box)
  2. be able to create different variants of the same data-type

From this:

interface Person {
   email: string
   /** @mockType {name.firstName} */
   firstName: string
}
interface Family {
  /** @mockType {name.lastName} */
  name: string
  members: Person[]
}

To this:

import faker from 'faker';
import type * as Types from './types';

export function Person(overwrites: Partial<Types.Person> = {}): Types.Person {
  return {
    email: faker.internet.email(),
    firstName: faker.name.firstName(),
    ...overwrites
  }
}

export function Family(overwrites: Partial<Types.Family> = {}): Types.Family {
  return {
    name: faker.name.lastName(),
    members: Array.from({ length: faker.random.number(8) }).map(() => Person()),
    ...overwrites
  }
}

I guess supporting exactly this would be to specific for this library and possibly extend its scope but a intermediate step would be to support a "raw" outputFormat like this

{
  "Person": {
     "email": { "fake": "internet.email" },
     "firstName": { "fake": "name.firstName" }
  },
  "Family": {
    "firstName": { "fake": "name.lastName" },
    "members": { 
      "array": {
        "range": [1, 8],
        "contains": [{ "type": "Person" }]
      }
    }
  } 
}

which could then be used to create such factories.


What's your opinion on this? If it sounds interesting, I'd like to create a PR.

No mock of heritage attributes in an attribute of a type that has inheritance

There is an issue when mocking attributes of interfaces that have inheritance.
Example file:

interface A{
   a: string
}

interface BA extends A{
   b: string
}

interface C{
   ba: BA
   c: string
}

Output:


interface A{
   a: string
}

interface BA extends A{
   b: string
}

interface C{
   ba: BA
   c: string
}

{
  "C": {
    "ba": {
      "b": "Suscipit corrupti id dicta dolores assumenda eum magni officia omnis. Consectetur minus qui occaecati odio repellat sunt et occaecati. Ex nulla explicabo. Eius quasi dicta et et nesciunt. Maiores sed molestiae voluptas fugit cumque omnis mollitia rerum illo. Repellat est atque recusandae nihil tempora iure."
    },
    "c": "Quia voluptatem minima nemo velit.\nPraesentium ut aut."
  }
};

There is no 'a' attribute on the output.
I think that the issue comes from the gatherTypes function

Support for multiple files

Hey, this is some fantastic work! I see this being the future of mocking within Angular and other applications using TypeScript.

Is there support for multiple files, or to target files based on an identifier such as all .model.ts files? If not, perhaps I can help.

Thanks,
Jamie

Using `number | null` ends up in an error

Hey 👋

I think I faced with a possible issue, the source type generated by the swagger-typescript-api package.

Steps to reproduce

  • Have a type with a nullable field:
    Failing Example:
    export interface ExampleKey {
    /** @format int64 */
    activeUntil: number | null;
    allowExportDashboard: boolean;
    email: string;
    firstName?: string;
    isValid: boolean;
    lastName?: string;
    }

If the ... | null removed, the mock will be created as expected.

Errors:

Online interface will throw the following error:
m[a] is not a function

CLI will throw the following error:
Unsupported Primitive type 173

Is it something expected or it is a bug?

In-memory mock generation

I'd like to provide interface types and generated mock data purely in memory. Is there a clean way of doing this? It seems like use of the "mock" function assumes that file system access is available and output is assumed to be to disk.

Output is not encoded correctly

The output is sent to stdout using console.dir() which wraps output in a string using these characters
�[32m �[39m
console.log does not wrap the result in quotes.

Throw Error when {[key: string]: string}

intermock/build/src/lang/ts/intermock.js:47
  throw Error(`Unsupported Primitive type ${syntaxType}`);
  
Error: Unsupported Primitive type 173

the typescript interface is like:

interface Action {
    value: {[key:string]:string};//,<未设置>
    tag: string;//,<未设置>
}

it throw error when meet value.

  1. Ask for new option that allow user set to avoid error, for example, meet unkown type, output {}.
  2. Or support the structure.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.