Coder Social home page Coder Social logo

pact-specification's Introduction

How to get started writing a Pact implementation

  • All new Pact implementations should wrap the Rust implementation using FFI calls, to allow us to roll out new features quickly and consistently across our 10+ Pact languages. Please do not start writing a new Pact implementation without talking to the current maintainers at slack.pact.io!

Introduction

"Pact" is an implementation of "consumer driven contract" testing that allows mocking of responses in the consumer codebase, and verification of the interactions in the provider codebase. The initial implementation was written in Ruby for Rack apps, however a consumer and provider may be implemented in different programming languages, so the "mocking" and the "verifying" steps would be best supported by libraries in their respective project's native languages. Given that the pact file is written in JSON, it should be straightforward to implement a pact library in any language, however, to get the best experience and most reliability of out mixing pact libraries, the matching logic for the requests and responses needs to be identical. There is little confidence to be gained in having your pacts "pass" if the logic used to verify a "pass" is inconsistent between implementations.

To support consistency of matching logic, this specification has been developed as a benchmark that all pact libraries can check themselves against if they want to ensure consistency with other pact libraries.

Pact Specificaton Philosophy

The Pact matching rules follow Postel's Law.

  • Be as strict as we reasonably can with what we send out (requests). We should know and be able to control exactly what a consumer is sending out. Information should not be allowed to "leak" silently.
  • Be as loose as we reasonably can with what we accept (responses). A provider should be able to send extra information that this particular consumer does not care about, without breaking this consumer.
  • When writing the matching rules, err on the side of being more strict now, because it will break fewer things to be looser later, than to get stricter later.

Note: One implications of this philosophy is that you cannot verify, using pact, that a key or a header will not be present in a response. You can only verify what is.

Goals for implementing a pact library

  • The DSLs should be as similar as possible, within the idioms of the language, to the original Ruby wording to help create a consistent Pact experience, and minimise overhead when switching between languages.
  • The matching logic for the requests and responses should be the same so that we can have the same amount of confidence that the integrations will work in real life no matter what language the system was written and tested in.

Logging in a pact library

Since some pact implementations call others, it's helpful to have guidelines for the log levels.

  • Error: Something has gone wrong or there were test failures
  • Warn: We think you may be using something incorrectly, or you’ve turned off some safety switches.
  • Info: You probably want to know this every time you run pact, and if tests are failing here is an explanation
  • Debug: Information to help users know exactly what is happening during their tests (eg if they want to debug a failing test)
  • Trace: Very detailled information to help maintainers debug pact

The default log level (if any) should be info.

Index

  • JSON schemas - Pact Specification as a series of JSON schemas. To see the key differences between versions, see https://github.com/pactflow/pact-schemas/blob/main/src/index.ts.

  • Version 1 - A spec that describes the existing matching in the ruby implementation, and provides test cases for implementations in other languages to ensure that matching is consistent.

  • Version 1.1 - Updated specification shared between Ruby, JVM and .Net versions.

  • Version 2 - Introduces non-language specific regular expression and type matching.

  • Version 3 - Introduces pact format for message queues and corrects some issues with V2.

  • Version 4 - Adds lots of new features, see RFC #71 for details.

pact-specification's People

Contributors

bethesque avatar bsix avatar cjwebb avatar goodgravy avatar mboudreau avatar mefellows avatar rholshausen avatar timothyjones avatar uglyog 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pact-specification's Issues

Best approach for supporting non-JSON serialization formats in pact

The below is a Request For Comment on the idea of adding support for non-JSON serialization in pact - before I do any work on trying to add this support for pact, I'd like to get thoughts and suggestions from the community on whether such a change to pact would be likely to be accepted, and feedback on the best way to go about it.

Motivation

JSON isn't a schema based serialization format, and so having some sort of contract or integration test is essential - without it, there would be no guarantee that producers and consumers were in sync at all. To my mind, pact tests cover the following bases:

  • The (implicit) schema that both producer and consumer are consistent.
    • This covers any API versioning concerns that might exist between producer and consumer.
  • A given route that a consumer service is expecting the producer to have exists and has the expected schema.
  • Particular types of requests / responses interact with the consumer / producer in expected ways (e.g. an invalid request produces a bad HTTP status code of some kind).

All of the above points also apply to protobuf (and other non-JSON encodings): admittedly protobuf does encourage patterns which support versioning (which I won't go into here), and there is a data schema that's shared between producer / consumer, but there's nothing forcing schemas to be in sync between services or to stop developers breaking backwards compatibility.

In a world in which services are loosely coupled, producers and consumers live in separate repositories - with the data schema living in a third repository - there's ample potential for services to find themselves out of sync with each other. To ensure services stay in sync, either an integration test or a contract test is required.

Currently there exists no tooling for contract testing with HTTP + protobuf, but from what I can work out, adding support to pact is both a desirable and tractable thing to do.

Suggested approach

Given protobuf, isn't the only non-JSON encoding that users might want to contract test using pact, my proposal to implement this functionality is encoding agnostic (there are lots of other encodings out there: flatbuffers, msgpack, SBE, thrift to name a few).

Suggested flow for non-JSON pacts

When generating a consumer contract and validating consumer code, the test code POSTs to the /interactions endpoint on the pact mock_service the details of the expected response when a given request is received. I suggest that when new interactions are being configured, that two fields are added: 1) encoding type, and 2) an opaque representation containing details of how to encode/decode the given request/response. Request and response matching / requests / responses would still be sent in JSON.

For every additional encoding (in addition to JSON), a new module in the mock_service and provider_verifier would be required, which would contain encoding-specific logic that uses opaque representation. This module translates the native format to a JSON representation, which can then be fed through to the standard mock_service matching logic - thereby keeping most of the code paths the same for JSON/non-JSON.

In terms of the consumer contract, in addition to the current JSON which specifies the contract, the following would be required: 1) the expected encoding type, 2) the opaque representation as mentioned at the start of this section. Given the opaque representation would likely obfuscate the rest of the contract, this would likely be stored in a seperate file to the JSON contract and referenced with a unique identifier.

The new consumer contract could then be used by an implementation of provider_verifier which supports the additional encoding in order to validate the producer.

Protobuf specifics

In terms of protobuf, the opaque representation of the message encoding is the MessageDescriptor, which is programming language agnostic, and thus straightforward to pass between pact test clients and the Ruby-based mock server.

Proof of concept

Given I'm at the point of having an idea of how to go about adding support for protobuf to pact, it's something I'm going to have a go at over the next few weeks once I have time. The main purpose of the proof of concept would be to gain more insight on the nicest way to add protobuf support, ahead of attempting to add support in a way which would be amenable to the community.

HTTP header behaviour in test cases differs from that in spec

The JVM test case asserts various aspects of HTTP header behaviour that is not mentioned in the spec, which says "Exact string match for expected header names and values." This makes it more difficult (frustrating) to implement a verifier. Two behaviours exist in the test cases:

  • header names are compared case-insensitive
  • whitespace after commas in header values is ignored when comparing values

For future implementors of the spec, please add a clarification to the header that replaces "Exact string match for expected header names and values." with words more accurately reflecting what an implementation should do.

How full an implementation of HTTP header value parsing should be implemented in order to allow comparison?

The ability to generalise what we expect from an array

I have a provider that returns ~16500 objects in an array for a given API-call. I would like to use pact-jvm to verify that the provider is behaving as expected, but since pact requires the number of items in an array to be exactly specified, I would have to specify that there should be ~16500 items in the array, which just isn't practical at all.

In many cases, it would make sense to say that what you require, is that there are "many" (more than 1) items in this array, and here is what they should look like.

I think perhaps a way to select one of the following ways for matching an array would be very useful:

  • The array should have 0 items (special case of next rule)
  • The array should have exactly these items (as today)
  • The array should have "many" items (accept anything that is more than 1, if all items match a single specification)

version 1.2

Hi there

I am using the .Net version of Pact, and want to be able to compare the response body without worrying about the property values (JValues) and instead just worry about the property names.

This is possible in Pact version 2 with the flexible body matching, but this version is a major change and the .net version is a long way off it.

I have added just the possibility of ignore property values in the response body in the .NET version of PACT.

I don't expect that this will be taken up by other language implementations, or even other users of the .NET version, but even so it would be useful to give this change a version, so that it can at least be rejected if unsupported.

I realise creating a whole new version for this might feel like it's a bit over the top, but I don't think it will hurt anybody else, and it will help me. The pact format is backwards compatible and adds a new feature so a minor version number makes sense semantic versioning wise.

Cheers

Cedd

Json path selector support

Hi there,
In our JSON models we do have a fair number of unions - arrays of objects with different structure. In order to cover all cases it seems we'll need to create a matrix of test data since there doesn't seem to be support for path selectors.

Is this something considered in V3 or something that could be implemented in a custom matcher?

Multiple providers with shared consumers

In our platform we have the concept of an 'adaptor' microservice to intermediate between each 3rd party providing the same capability. All adaptors are required to provide (shared) consumers with a consistent external contract - the mapping to each 3rd party is then isolated within each adaptor.

What's the best way of using Pacts to test the same contract against each adaptor? Our initial ideas are below.

  1. We could make our consumer Pact tests aware of each producer (adaptor). The tests could iterate through each adaptor, generating multiple Pact files, or we could modify the Pact implementation to generate multiple identical pact files given an array of producers. This has the downside that we have to modify our consumer(s) source (albeit trivially) when we add a new adaptor. Not great as we want to scale to ~200 3rd parties.

  2. Use something other than Pact. We could validate the adaptor against our Open API spec, potentially as part of run-time monitoring. In that case we would then run consumer Pacts only against a stub or template implementation of our adaptor, which is auto-generated from our Open API spec.

Any other ideas?

Full spec for each version?

It looks like each branch describes the changes in spec from the previous version. Is there full spec available for v2 or v3?

Feature request - `array_contains` or `each_like` with multiple elements

Say I want to talk to a service to create a pony. We know the response will be:

  {
     id: 1,
     history: [
       { event: "create", date: "01-01-2000", id: 123 },  
       { event: "health_check", date: "01-01-2000", id: 124 },  
       { event: "verify", date: "01-01-2000", id: 125 },  
       { event: "approve", date: "01-01-2000", id: 126 }
     ]
  } 

However, I only care IDs of two particular events - create and approve.

So my Pact is:

expected_response = {
  id: Pact.like(123),
  history: [
    {
      event: 'approve',
      id: Pact.like(2)
    },
    {
      event: 'create',
      id: Pact.like(1)
    }
  ]
}

Note I don't even care the order within the history array.

This Pact setup won't work because Pact will try to exact match on history array. And then it will complain about array order and length not match.

The current each_like method only accepts one element.

I think the ideal scenario will be having a new matcher called array_contains which allow us to match and generate multiple elements in an array; and ignore array length and order.

matching clarification

I am working on .net port of pact. There is something unclear to me..
Assume I have a following test case:

{
  "match": true,
  "comment": "top level array matches",
  "expected": {
    "headers": {"Content-Type": "application/json"},
    "body" : [ {
      "dob" : "06/11/2015",
      "name" : "Rogger the Dogger",
      "id" : "a_string",
      "timestamp" : "2015-06-11T13:17:29"
    }, {
      "dob" : "06/11/2015",
      "name" : "Cat in the Hat",
      "id" : 1284270029,
      "timestamp" : "2015-06-11T13:17:29"
    } ],
    "matchingRules" : {
      "$.body[*].id" : {
        "match" : "type"
      }
    }
  },
  "actual": {
    "headers": {"Content-Type": "application/json"},
    "body": [
      {
        "dob": "11/06/2015",
        "name": "Bob The Builder",
        "id": 1234567890,
        "timestamp": "2000-06-10T20:41:37"
      },
      {
        "dob": "12/10/2000",
        "name": "Slinky Malinky",
        "id": "a_string",
        "timestamp": "2015-06-10T22:98:78"
      },
      {
        "dob": "12/10/2000",
        "name": "Jerry Smith",
        "id": "a_string",
        "timestamp": "2015-06-10T22:98:78"
      }
    ]
  }
}

Which result is it going to produce and why?

Content-Type resolution

From specs

If the Content-Type header, is not present, then:

1. OPTIONAL - The content type can be determined from the first few characters of the body (know as a magic number test).
2. default to either application/json (as V1) or text/plain.

Shouldn't specification be specific about that? For example now I assumed "application/json" by default, so my implementation conforms to specs, but it fails some test-cases, because they assume "text/plain" by default.

Check that we have a test case for allowing extra headers in the provider response

Just found this in the wiki, and wanted to check we had a test case for it. Don't have time to look right now.

But Pact breaks Postel's law for request headers
The exception to this is the request headers - we have found that frameworks tend to add their own headers, and that maintaining these can be extremely tedious, so be aware that if you are using a header that will change the behavior of the provider, you must specify it in your expectations.

At least X feature

@uglyog, I'm not super keen on the way the current implementation of the 'at least' feature means we have to string parse the match value to work out how many items need to match.

https://github.com/bethesque/pact-specification/blob/version-2/testcases/request/body/array%20with%20at%20least%20two%20elements%20expected.json

Also, it seems that this would be better named "starting with". I was confused as to why this example was a failure until I realised that order mattered: https://github.com/bethesque/pact-specification/blob/version-2/testcases/request/body/array%20with%20at%20least%20one%20element%20but%20the%20element%20is%20different.json

I'm also not sure why we need to put in the number, as I'm pretty sure you pointed out that the number of elements in the expected array indicates how many we need to match?

Invalid JVM testcase? Incorrect spec?

I'm trying to validate a new verifier against the test corpus.

The JVM testcase in the version-2 branch "testcases/response/body/array with regex matcher xml.json" appears to have an invalid JSON path spec according to the pact specification, as it uses "$.body.myDates[*].date['#text']" (the ['#text'] is not valid, according to the spec).

Which is correct, the spec or the test case?

Should we store the "actual" request data instead of/as well as the "expected" in the pact file?

From @uglyog comment on https://gist.github.com/bethesque/5a35a3c1cb9fdab6dce7

I would like to see a mechanism to use the value from the received request. The idea being that some values need to be present, but we are unable know what the value actually will be because they are auto generated. Thus it would be convienient to say: match("") and then use the value from the request if it matches.

One example is a request to the following resource:

PUT /events/7d83c33d-c006-4f8e-b736-363f4ececde8 HTTP/1.1
Content-MD5: oZGEVpiIWE2KlTsp9aKLag==
X-HMAC-DATE: Mon, 05 May 2014 07:10:34 GMT
Authorization: HMAC BABYLON 105bf4cef0953f9a678b976b0d045d7b4d90b98870cca8db9b73c127b45d5d14
User-Agent: Jakarta Commons-HttpClient/3.1
Host: localhost:9292
Content-Length: 300
Content-Type: application/json; charset=UTF-8

{"event_id":"7d83c33d-c006-4f8e-b736-363f4ececde8","timestamp":"2014-05-05T07:10:34.031Z","host":"rholshausen.engr.acx","ip_address":"0:0:0:0:0:0:0:1%0","event_type":"DOCUMENT:EVENT_VIEW_DOWNLOADED","user":{"id":1879049107,"username":"poleary","organisation":1879048492},"document":{"id":1879104598}}"
The Path includes a UUID of the new resource, so I would like to say:

.upon_receiving("a request to store a new event")
    .with( method: :put, path: matching(/\/events\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/) )

Then if it matches, the generated value in the pact file can be the original request value.

Review of pact-json-schema v2

I added the schema for pact v2 to the pact-json-schema codebase. Do you mind doing a review for correctness?

https://bitbucket.org/atlassian/pact-json-schema/src/8c17153c5658b9e2dff8404c7cc3751fe3e9ebdd/schemas/v2/schema.json?at=master&fileviewer=file-view-default

The differences between v2 and v1 schemas are the addition of matching rules to request and responses as well as the removal of the legacy provider_state (now providerState) property on the interaction object.

Error in v2 spec?

The v2 spec has an example of path matching and weighting but it seems to be in error - the sample has item id 102 at index 2 but the following discussion about resulting weightings and statement "So for the item with id 102, the matcher with path $.body.item1.level[1].id and weighting 64 will be selected." have it at index 1. Unless I'm missing something fundamental about indexes and how they work in the interpretation of the matching rule paths, the example or discussion from it should be corrected.

Feature Request: support for message chaining

moved from https://github.com/realestate-com-au/pact/issues/103
We are using PACT goodness for testing our micro-service interactions, and one of our services uses webhooks to handle asynchronous, long running tasks.

Currently, the only way to PACTify this (as far as we know) is to have bi-directional pacts, one for the consumer to the provider for the original request, and one from the provider back to the consumer to the webhook callback.

This feels a littly iffy to me, I'd be happier with a single PACT file that goes along the lines of:

animal_service.given("an alligator exists").
    upon_receiving("a request for an alligator").
    with(method: :get, path: '/alligator', query: 'callback=/alligator/response').
    will_respond_with(status: 200)
    will_callback_with(method: :post, path: '/alligator/response', body: {name: 'Betty'})

`

An immediate issue I can see (going from the example in the readme) is that the test is for the AnimalServiceClient wheras the callback would hit the controller of the consumer service.

Thoughts/Tips? Anyone done anything similar

Existential checking of lists

Currently pact v2 spec allows us to write a provider JSON that can check array/list elements all (universally) have a particular property

given
{ "_links": { "item": [ { "href": "something" }, {"href": "something-else"}] }] } }

e.g. for HAL:
body._links.items[*].href=<string type>

What seems to be missing, and I can't see if this is by design, is for looking for one item in particular

e.g.
body._links.items[?].href="my_specific_thing"

  1. IS this by design/opinion?
  2. I believe it would help support growing contracts, as we can support heterogeneous lists.

I know I have the option of modelling these things as keys, but the HAL spec does expect lists of things.

I also know I don't have to use pact. If it's not something you'd like to support, then I may write up something to add to the matching gotchas.

Rolling out breaking changes where consumer goes first

I'm thinking about how to keep the Pact tests green when you want to roll out a breaking change to an API. Here is a concrete example to help make things clear.:

Imagine I have a get customer api that returns this json response body:

{
    "name": "Bob Smith"
}

I want to change the response body to this:

{
    "firstName": "Bob",
    "lastName": "Smith"
}

In this example the consumer of this API has a pact test for this integration. The consumer also will not be able to deploy if the Pact file does not go green when verified against the production version of the provider.

The easiest way to make this change is to update the provider to include both versions of the responses at the same time.

{
    "firstName": "Bob",
    "lastName": "Smith",
    "name": "Bob Smith"
}

Once the provider has rolled this change out to production the consumer can consume the new API and the pact file containing updated examples will go green when verified against the production version of the provider. Everything went smoothly in this scenario.

Things get more tricky if the consumer wants to go first and support receiving both versions of the responses:

  • If this change is made and correctly Pact tested it will not go green when verified against the production version of the provider because this version of the provider does not yet support the new API. This blocks the consumer from deploying.
  • If the consumer avoids writing the Pact test this will allow them to deploy to production but will block the provider from removing the old API as the Pact examples still require it. This is also an undesirable thing to do as the new API is not tested with Pact before it hits production.

Is there a good way for the consumer to go first? I was thinking that the Pact specification should allow optional values in the response but this seem to have been discussed before and decided to be a bad idea. Any guidance would be appreciated.

I raised the issue here as I'm wondering if the Pact specification needs to be changed to support this use case.

Assure property exists

I'm not very satisfied with the matchers. With current matchers it's possible to say that if a property exists it has to be of a special type or must have a special content, but it's not possible to assure, that the property has to exist at all. For example, how would you assure with matchers that with

body: {
  "abc": "def"
}

property "abc" is a string and must be present in the body?

matching rule

"$.body.*": 
{
"match": "type"
},

would not give an error, if only

{}

is sent.

Add test cases for int/doubles

Expect 1, Actual 1.0.

Does this match? (It does in Ruby, suspect it doesn't in the JVM)

Expect like(1), Actual 1.0

Does this match? (It doesn't in Ruby)

Matching Arrays without structure

Is it possible to match an array where each array element it _not_ a json object?

i.e.

def expectedArray = ['12:00', '12:15', '12:30']

and then in my matcher

withBody {
   foo minLike(1) {
     regex('\\d{2}:\\d{2}', '12:00')
   }
}

Based on the doco, it seems each array matchers requires the element of the array to be a json object with some structure.

Support matcher on Number field like 'response status'

we are facing a situation like:
Provider side will respond 4XX for different fail case(bad request)
however, Consumer side doesn't quite care about the response status code. just if it's other than 200, consumer side will just raise an exception with error message from the response.

So the contract for request error case looks like, Consumer will expect non-200 code, which may need the pact implementation support matcher on response status code field(which is a Number)

What about multiple consumers?

More specifically, consumers using the same functionality defining their own API. What happens if the consumers have different pact specs for the same provider, on the same functionality?

Also, wouldn't having multiple consumers using different parts of one producers cause the producer's API doc to be fragmented, hard to review?

Sorry, I'm new to this, if these issues have been addressed.

Multiple matchers?

The spec for v2 says you can only use one matcher at a time: Regex, Type, MinType or MaxType. But what if you want use MinType and MaxType to guarantee the number of minimum and maximum elements of an array?

Introduce message queue support

Since the approved spec for v3 is here and it includes messages support, a possible support for message queue protocols should be made.

There should probably be a factory for that, which would make different queueing protocols possible to implement and use. In example, AMQP, NATS, etc.

Potential new feature - add an optional comments to the interaction

I had a discussion with Andras and Tim the other day that resulted in this suggestion:

some_provider
  .uponReceiving("a request to do something that is not quite clear from just the request and response data")
   ...
  .will_respond_with(202)
  .comment("This allows me to specify just a bit more information about the interaction")
  .comment("It has no functional impact, but can be displayed in the broker HTML page, and potentially in the test output")
  .comment("It could even contain the name of the running test on the consumer side to help marry the interactions back to the test case")
{
  "interactions": [
    {
      ...
      "comments": ["This allows me to specify just a bit more information about the interaction",
        "It has no functional impact, but can be displayed in the broker HTML page, and potentially in the test output",
        "It could even contain the name of the running test on the consumer side to help marry the interactions back to the test case"]
    }
  ]
}

cc: @mefellows @uglyog @TimothyJones @abubics

Matcher for dynamic Object keys

Pact Matcher for objects with dynamic keys

My use case is pretty specific but i feel like it might be common.
I have an systemMessage object that has a very consistent schema that i defined like this

export const systemMessage = {
  id: like(123456),
  message: like('some text here'),
  priority: term({
    matcher: 'LOW|MEDIUM|HIGH|CRITICAL',
    generate: 'HIGH'
  }),
  destination: term({
    matcher: 'EVERYWHERE|SOMEWHERE|ELSEWHERE',
    generate: 'EVERYWHERE'
  })
};

I return a very high volume of these objects and to simplify my render process I use a hash where each message is keyed by it's ID.

const systemMessages = {
    123456:  MessageWithID123456
    ....
}

Since the objects contained in the hash are of a specific type I would like a function akin to eachLike for objects that simply validates that the values in the object conform to the pattern above and ignores the keys.

{
    systemMessages: objectLike({
      id: like(123456),
      message: like('some text here'),
      priority: term({
        matcher: 'LOW|MEDIUM|HIGH|CRITICAL',
        generate: 'HIGH'
      }),
      destination: term({
        matcher: 'EVERYWHERE|CMS',
        generate: 'EVERYWHERE'
      })
    })
}

I'm including a link to the react-immutable-proptypes project. They have a function called ImmutablePropTypes.mapOf() which does what I described.
https://github.com/HurricaneJames/react-immutable-proptypes#api

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.