Giter Site home page Giter Site logo

apivore's Introduction

Build Status

Code Climate

Apivore

Automatically tests your rails API against its OpenAPI (Swagger) description of end-points, models, and query parameters.

Currently supports and validates against OpenAPI 2.0, (see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md)

Installation

To use Apivore, add the following to your Gemfile:

gem 'apivore'

WARNING: If apivore is listed in the Gemfile above rspec then some issues, specifically NameError: uninitialized constant RSpec::Mocks, may arise when trying to run specs.

Usage

Create a new request spec in spec/requests:

require 'spec_helper'

RSpec.describe 'the API', type: :apivore, order: :defined do
  subject { Apivore::SwaggerChecker.instance_for('/swagger.json') }

  context 'has valid paths' do
    # tests go here
  end

  context 'and' do
    it 'tests all documented routes' do
      expect(subject).to validate_all_paths
    end
  end
end

using the path to your application's Swagger 2.0 documentation. The convention is /swagger.json.

This will validate the json against the Swagger 2.0 schema and allow you to add tests for each documented endpoint combination of a path, method, and expected response.

If your Swagger documentation contains a schema for the response model, the generated tests will test whether the response conforms to that model.

For paths that take parameters, listed in the Swagger docs like /deals/{id}.json, values need to be passed to Apivore to substitute in to access the responses generated by your test data.

This is accomplished by passing the params into the validates function.

context 'has valid paths' do
  let(:params) { { "id" => 1 } }
  specify do
    expect(subject).to validate(
      :get, '/deals/{id}.json', 200, params
    )
  end

  # or alternatively

  it { is_expected.to validate( :get, '/deals/{id}.json', 200, params ) }
end

A query string can be specified with the _query_string key as follows:

expect(subject).to validate(
  :get '/deals', 200, {"_query_string" => "title=Hello%20World&edition=3"}
)

Parameters in the query string are not validated or processed by Apivore in any way.

Post parameters can be specified with the _data key as follows:

expect(subject).to validate(
  :post '/deals', 200, {"_data" => {'title' => 'Hello World'} }
)

HTTP headers can be specified via the _headers key:

expect(subject).to validate(
  :get '/deals', 200, {"_headers" => {'accept' => 'application/json'} }
)

Your Swagger.json can be validated against additional custom schemata, for example to enforce organisation API documentation standards, by using the following syntax:

it 'additionally conforms to a custom schema' do
  expect(subject).to conform_to("<your custom schema>.json")
end

We have included an example [here] (data/custom_schemata/westfield_api_standards.json). The file path to this custom schema is stored in Apivore::CustomSchemaValidator::WF_SCHEMA, if you wish to use it.

Run the tests as part of your normal rspec test suite, e.g., rake spec:requests

Useful Resources

License

Copyright 2014 Westfield Labs Corporation

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

This project includes and makes use of the OpenAPI (Swagger) 2.0 schema json (Copyright 2016 The Linux Foundation. Released under the Apache License) included here as data/swagger_2.0_schema.json

It also includes a copy of http://json-schema.org/draft-04/schema, included as data/draft04_schema.json. These schemata are included to prevent network resource fetching and speed up validation times considerably.

Contributors

apivore's People

Contributors

adamcohen avatar ashoda avatar ekalinichev avatar gingermusketeer avatar gwagener avatar gwshaw avatar hornc avatar jszwedko avatar leondewey avatar mastfish avatar mastfissh avatar matt-wratt avatar nblumoe 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

apivore's Issues

Rails 5.0 deprecation warning

When running against Rails 5.0 you are shown the following warning:

DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as

Examples:

get '/profile',
  params: { id: 1 },
  headers: { 'X-Extra-Header' => '123' },
  env: { 'action_dispatch.custom' => 'custom' },
  xhr: true,
  as: :json
 (called from matches? at /.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/apivore-275e799ea72c/lib/apivore/validator.rb:21)

Errors on non-JSON responses

It seems the library only supports JSON responses. I have an endpoint that returns an image, and the result of testing it is a JSON::ParserError. There are a number of places where the response is parsed as JSON, but the first one where the error occurs is in the response_body method of validator.rb.

Does not handle empty response case

From the swagger documentation:

Some responses, such as 204 No Content, have no body. To indicate the response body is empty, do not specify a content for the response:

https://swagger.io/docs/specification/describing-responses/#empty

If you try and test such an endpoint with apivore, you get the following exception:

Swagger doc: /swagger.json missing response model for get request with /liveness for code 200

It looks like the validator code https://github.com/westfieldlabs/apivore/blob/master/lib/apivore/validator.rb#L83 should be checking to see if response body is null before raising an exception about missing response models

route defaults not considered in path parameter substitutions

Apivore does not look at the existing parameters as from a default in the routes file in making the path substitutions. For example, from the YML file

paths:
'/centres/{centre_id}/movies.{format}':

Not supplying the {format} parameter in the APIvore hash will fail with "No substitution data found..." even though the parameter has been supplied by a default in the route file.

Is this project still being maintained?

CONTRIBUTING.MD says:

We aim to respond to pull requests within a few business days, and, typically, within one business day.

Looking at issues and open PRs, it seems like it's been about a year since any activity happened on this project, despite a good number of Issues and PRs that have happened since then. I recently found a small issue and considered submitting a PR, but it doesn't look like there's much point in the current situation.

I'm the last person to play the blame game and demand anything from open source maintainers, so don't expect that. But this gem has >100,000 downloads on RubyGems, and there's a reason for it. It's really useful to a lot of people, and whether or not Westfield Labs has time for it, someone should be maintaining it actively. It would be a shame to let it die with Rails 5 and the compatibility issues that has introduced.

Perhaps the original maintainers would be interested in passing on the responsibility to others?

Support multiple methods for loading a swagger document.

There are various requests around supporting loading swagger docs by different means.
Current behavior

  • Load JSON from a path relative to the application

Requested:

  • Load YAML from a path relative to the application
  • Load JSON from local file
  • JSON string

It'd make sense for us to look at the various request to determine the ideal approach to makes loading a swagger doc a bit more flexible.

My initial thought is to add support for a Hash or a JSON string in addition to what we currently support, which would afford people enough flexibility to decide how they'd like to load the swagger doc.

cc: @gwshaw @jreece1567

Incorrect error message for substitute data error

If the .yml file has this:
paths:
'/centres/{centre_id}/movies.{format}':

and the swagger spec has this:

apivore_setup '/centres/{centre_id}/movies.json', 'get', '200' do
{ 'centre_id' => @centre_id}
end

(note".json" rather than {format} parameter.

The error generated is:

  1. the API path /centres/{centre_id}/movies/{movie_id}.{format} method get response 200 responds with the specified models
    Failure/Error: path.scan(/{([^}]*)}/).each do |param|
    URI::InvalidURIError:
    No substitution data found for {centre_id} to test the path /centres/{centre_id}/movies/{movie_id}.{format}.
    Add it via an:
    apivore_setup '', '', '' do
    { 'centre_id' => }
    end
    block in your specs.

    /Users/george/.rvm/gems/ruby-2.2.0/bundler/gems/apivore-896dcb54528e/lib/apivore/rspec_builder.rb:30:in `each'

    /Users/george/.rvm/gems/ruby-2.2.0/bundler/gems/apivore-896dcb54528e/lib/apivore/rspec_builder.rb:30:in`apivore_build_path'

    /Users/george/.rvm/gems/ruby-2.2.0/bundler/gems/apivore-896dcb54528e/lib/apivore/rspec_builder.rb:77:in `block (3 levels) in validate'

Either the path should not match, it should complain about the correct substitution parameter, or be silent and just use the '.json' from the supplied path.

Is it still maintained ?

Is this project is still maintained ?

If so,
Are you planning to merge/reject pending PRs ?

If not,
Could be great to mark it as un-maintained and/or looking for maintainers.

Responds matches should support reference objects

Currently only inline responses with a defined schema are supported.

Especially when it comes to describing error responses you typically want to define them under the top level responses: key and reference them via

get:
  responses:
    "401":
      "$ref": "#/responses/Unauthorized"

This does however currently result in: Swagger doc: /doc/api.json missing response model for get request with /xxx for code 401

Json_Schema gem needs higher minimum version

The requirement of jason_schema gem 2.5 passes the Gem's test, but in-use fails unless jason_schema 2.6 or greater is used. Bundler is not, for unknown reasons, using the latest version (2.6.1) and the bundled version (2.5) fails with webmock issues. Removing Apivore from the gem file shows no other dependencies on the jason_schema gem.

Response matching needs to support `default` responses

Currently, explicit spec validation using the expect(subject).to validate method will not work with default response types because the validator converts the argument to an int and then the checker converts back to a string (so 'default' becomes 0 becomes '0')

Allow references for responses

I would like to be able to reuse responses by setting references, like this:

"paths": {
  "/path.json": {
    "get": {
      "resource": {
        "401": {
          "$ref": "#/responses/NotLoggedIn"
        }
      }
    }
  },
"responses": {
  "NotLoggedIn": {
    "schema": {
      "$ref": "#/definitions/Error"
    }
  }

Currently, it ignores the reference, letting any value pass. My current attempt is to fix this is by altering Apivore::Swagger.each_response:

method_data.responses.each do |response_code, response_data|
  schema_location = nil
  if response_data.schema
    schema_location = Fragment.new ['#', 'paths', path, verb, 'responses', response_code, 'schema']
  elsif response_data.send(:$ref)
    schema_location = Fragment.new response_data.send(:$ref).split('/').push('schema')
  end
  block.call(path, verb, response_code, schema_location)
end

But this raises "NoMethodError: undefined method `validate' for {"$ref"=>"#/definitions/Error"}:Hash"

  • /.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/json-schema-2.6.1/lib/json-schema/validator.rb:114:in `validate'
  • /.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/json-schema-2.6.1/lib/json-schema/validator.rb:276:in `fully_validate'
  • /.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/apivore-1.6.0/lib/apivore/swagger_checker.rb:26:in `has_matching_document_for'
  • /.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/apivore-1.6.0/lib/apivore/validator.rb:95:in `check_response_is_valid'
  • /.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/apivore-1.6.0/lib/apivore/validator.rb:65:in `post_checks'
  • /.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/apivore-1.6.0/lib/apivore/validator.rb:28:in `matches?'
  • ./spec/requests/api_spec.rb:18:in 'block (3 levels) in <top (required)>'

Any plans for supporting this?

Support for Rails 5

Rails 5 is about to be released, and Apivore has actionpack and activesupport dependencies set to "~> 4", which doesn't allow to use it with apps that are based on Rails 5 beta.

Suggestion is to create "rails5" branch where dependency versions would be set to ">= 4", "< 6" and if Rails 5 users will report errors, fix them in this branch. When Rails 5 gets out of beta, merge this branch to develop.

Other approach would be just change versions in develop, since developers not using Rails 5 beta won't be affected by any related bugs anyway, and developers using beta versions probably know what they are doing.

using apivore in seperate test framework

  • I am using apivore in a separate(custom) test framework.
  • So apivore is not used with a rails app. i am just testing some rest APIs
  • i had to override follwing method to return the swagger.json file located (temp) in my framework
def fetch_swagger!
     JSON.parse(File.read(LOCAL_SWAGGER_JSON_PATH))
   end

here is my test:

describe 'the API', type: :apivore, order: :defined do
  before do
    byebug
    @json = Apivore::SwaggerChecker.instance_for(LOCAL_SWAGGER_JSON_PATH)
  end
  context 'testing' do
    let(:params){}
    it 'identify' do
         expect(@json).to validate(
         :post, "/identify", 200, {
                           "_data" => {user_id: 'xxx', email: "[email protected]"},
                           "_headers" => {'X-Outbound-Key' => 'xxxx'}
                       }
     )
    end
  end
end

Error after executing test:

Failure/Error:
        expect(@json).to validate(
           :post, "/identify", 200, {
                             "_data" => {user_id: 'xxx', email: "[email protected]"},
                             "_headers" => {'X-Outbound-Key' => 'xxx'}
                         }
       )

     NoMethodError:
       undefined method `call' for nil:NilClass

How can i user Apivore:

  • with non rails app?
  • by loading local swagger.json file?

Ignore vendor specific tags paths

Vendor specific tags are allowed by the Swagger standard in most places in the form
"x-something": "some value"

The submitted PR ignores vendor specific tags under the paths tag.

How to handle response?

Hello. Sometimes I need to check the response manually.
For example, I have an endpoint, it should return an array of objects. I want to check response size (is it more than 0?). How could I do it?

Can README clarify the necessary elements for specs to run in order?

I spent basically all of today trying to figure out how to get apivore specs to run in the appropriate order so the grand-finale spec will pass.

For future developers, it might help to clarify that:

  1. The grand-finale spec has to go last
  2. It's necessary to specify order: :defined on the top context
  3. You can't define specs in other files (unless you include them via shared_examples)
  4. The and context is actually necessary because of RSpec's recursive method of spec ordering

Won't help me at this point, but it might make future devs' intro to apivore a little smoother.

Also, thanks so much for this awesome tool! Despite my rough intro, it's saving our team a lot of time and giving us much greater confidence that our API actually matches the docs we've set up for it.

undefined method `application' for Rails:Module

anyone run into this

undefined method `application' for Rails:Module
# xxxx/gems/ruby-2.2.3/gems/apivore-1.4.5/lib/apivore/swagger_checker.rb:75:in `fetch_swagger!'

running Rails 4.2.4 on Ruby 2.2.3

Support for using a JSON string rather than a URL path?

I have a scenario where I need to preprocess the swagger.json before giving it to apivore to validate (translating x-nullable to adding "null" to the type list for a given property). I can take a crack at implementing this, but wanted to see if it the change would be accepted first.

Thank you!

signed user?

What about a signed user? Does apivore supports it? I actually created workaround in my tests, but may be there is a better way.

You are setting a key that conflicts with a built-in method Apivore::Swagger#version

Rest of the error:

/$userpath/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/apivore-1.6.2/lib/apivore/swagger.rb:19.

I assume it's talking about this line in my request spec:

subject { Apivore::SwaggerChecker.instance_for('/docs/swagger.json') }

However to me it looks like it's setup exactly as the docs suggest. Seems like a bug with the gem.

Support having path level parameters

Currently apivore expects everything under a given route, e.g. /posts, to be a HTTP verb, but parameters is also supported (to specify parameters that are required by each verb under the path).

E.g.

...
paths:
  /posts/{id}:
    parameters:
      - name: id
        in: path
        type: integer
        required: true
    get:
      ...
    put:
      ...
...

Fails to pull swagger json

apivore does not succeed on pulling a swagger JSON. After not having had any success with the proper, local JSON, we tried the one of the Swagger Pet demo, which did not work either:

1) the API and tests all documented routes
     Failure/Error: subject { Apivore::SwaggerChecker.instance_for('http://petstore.swagger.io/v2/swagger.json') }

     RuntimeError:
       Unable to perform GET request for swagger json: http://petstore.swagger.io/v2/swagger.json - undefined method `call' for nil:NilClass
       Did you mean?  caller.
     # /Users/nblu/.rvm/gems/[email protected]/bundler/gems/apivore-275e799ea72c/lib/apivore/swagger_checker.rb:78:in `rescue in fetch_swagger!'
     # /Users/nblu/.rvm/gems/[email protected]/bundler/gems/apivore-275e799ea72c/lib/apivore/swagger_checker.rb:75:in `fetch_swagger!'
     # /Users/nblu/.rvm/gems/[email protected]/bundler/gems/apivore-275e799ea72c/lib/apivore/swagger_checker.rb:70:in `load_swagger_doc!'
     # /Users/nblu/.rvm/gems/[email protected]/bundler/gems/apivore-275e799ea72c/lib/apivore/swagger_checker.rb:64:in `initialize'
     # /Users/nblu/.rvm/gems/[email protected]/bundler/gems/apivore-275e799ea72c/lib/apivore/swagger_checker.rb:6:in `new'
     # /Users/nblu/.rvm/gems/[email protected]/bundler/gems/apivore-275e799ea72c/lib/apivore/swagger_checker.rb:6:in `instance_for'
     # ./spec/requests/api_spec.rb:4:in `block (2 levels) in <top (required)>'
     # ./spec/requests/api_spec.rb:12:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # NoMethodError:
     #   undefined method `call' for nil:NilClass
     #   Did you mean?  caller

We are on Rails 5.0.0

Not understanding it

I always get this:
{code}
Failure/Error: subject { Apivore::SwaggerChecker.instance_for('http://localhost:8000/api.json') }
RuntimeError:
Unable to perform GET request for swagger json: http://localhost:8000/api.json - undefined method `call' for nil:NilClass.
{code}

I'm not sure what is the problem. According to the readme I did everything correctly. My only guess is, that the .json-file does not fully comply with swagger specification in some way? As the error message is not really helping, can someone tell me where to look for my mistake?

Providing query and path parameters?

The readme say to provide dummy data for a parameter in the path, you can use the following create a params variable and attach it to the end of the method like so:

:get, '/url/{id}/moreurl', 200, params

It also says you can provide query parameters like this:

:get, '/url/{id}/moreurl', 200,{"_query_string" => "title=Hello%20World&edition=3"}

but what about both together? There are no docs for that and I keep getting an error saying wrong number of arguments, given 5, expected 3..4.

Surely there's support for it and I'm just blind? Hoping so anyway.

Repo headline & gem description claim to test query parameters (it doesn't)

This repo bills itself as:

Tests your rails API against its Swagger description of end-points, models, and query parameters.

But in the README, it says:

Parameters in the query string are not validated or processed by Apivore in any way.

which is actually the behavior.

I would find it very useful to verify the query parameters, but in the meantime, the repo headline shouldn't claim it does something it doesn't.

Uninitialized constant Apivore

I've followed the guide and this is the result.
Running specs with rake spec:requests it works correctly.

Running specs with rspec spec/requests the result is:

Failure/Error: subject { Apivore::SwaggerChecker.instance_for('/swagger.json') }

     NameError:
       uninitialized constant Apivore

I've tried to require apivore inside my _spec and the error was:

 undefined method `application' for Rails:Module

I've followed the instructions here #75 adding, also, require 'rails' and the error was:

RuntimeError:
       Unable to perform GET request for swagger json: /swagger.json - undefined method `call' for nil:NilClass.

I need to require something more?

OpenAPI 3.0

Thanks for the amazing project. I'm not involved at the moment and don't expect anything.

OpenAPI 3.0 Spec has been out for a while, I was wondering if there are any plans for supporting that? Thanks <3

Apivore hides parsing errors

If there is a parsing error in the Swagger docs file, YAML in my case, Apivore hides this error by failing with 'each_response': undefined method 'each' for nil:NilClass (NoMethodError) at https://github.com/westfieldlabs/apivore/blob/master/lib/apivore.rb#L26.

The error is present in session.response.body at https://github.com/westfieldlabs/apivore/blob/master/lib/apivore/rspec_builder.rb#L51, but gets lost when creating the Mash.

Apivore should report failures instead of just dying itself. Probably bubbling the parsing error would be fine. This would provide the line numbers of the parsing error.

redistribution request

Hi.
It looks like this project is not maintained.
Is this still maintained?, otherwise if you do not mind, we want to redistribute this awesome api test tool.

We look forward to hearing back from you.

RuntimeError: Unknown/unsupported Swagger version to validate against.

Hi,

I followed the readme, installed apivore, but I get an issue that I can't manage to get rid of while running my specs

When I run my specs, I got this issue, that arises upon the call of instance_for for Apivre::SwaggerChecker :

RuntimeError: Unknown/unsupported Swagger version to validate against: 
from /home/shideneyu/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/apivore-1.4.0/lib/apivore/swagger.rb:18:in `validate'

(after looking at the gem, I noticed that the variable 'version', alias of 'swagger' is nil (in /lib/apivore/swagger.rb); I added a debugger there for testing purposes and runned my tests upon it to discover this.)

My spec:

RSpec.describe 'Site API', type: :apivore, order: :defined do
  subject { Apivore::SwaggerChecker.instance_for('/api.json') }

  context 'has valid paths' do
    let(:params) { { "id" => 1 } }
    specify do
      expect(subject).to validate(
        :get, '/sites/{id}/pages/{id}.json', 200, params
      )
    end

    # or alternatively

    # it { is_expected.to validate( :get, '/deals/{id}.json', 200, params ) }
  end

  context 'and' do
    it 'tests all documented routes' do
      expect(subject).to validate_all_paths
    end
  end
end

By the way, as you can see in the attachment, my Swagger UI can successfully test the endpoint and renders 200, and the inputted url is http://localhost:3000/api.json

swaggerrr

Allow use of full URL for consistency check

Apivore assumes that the master document swagger is at a fixed address of http://<host>/swagger.json. This is limiting in that the protocol, path, and any authentication cannot be specified. Simply using the full URL addresses some of these issues, thus:

    it 'has definitions consistent with the master docs' do
      expect(subject).to be_consistent_with_swagger_definitions(
        'https://api.westfield.io/swagger/1.json', 'deal'
      )

Looking for http allows the current behaviour as well as fully specified URL.

Yaml support?

It would be great go have, since currently editing the yaml file.. having a .yaml and a .json would be a duplication.

URL with URL-unsafe characters causes invalid URI errors

I'm testing an API where we have the name of the resource as the unique identifier. If the name includes a space or any other URL-unsafe character, I see the following:

Failure/Error: it { is_expected.to validate(:get, '/resources/{name}', 200, params) }
URI::InvalidURIError:
 bad URI(is not URI?): http://www.example.com:80/resources/name of thing

I would expect apivore to convert this to

/resources/name+of+thing

so my tests can remain legible.

I'm happy to write a patch; it would just involve adding CGI::escape to

path = path.gsub "{#{key}}", data[key].to_s
as is done internally in Rails' Object#to_query (see https://github.com/rails/rails/blob/52ce6ece8c8f74064bb64e0a0b1ddd83092718e1/activesupport/lib/active_support/core_ext/object/to_query.rb#L12).

Please let me know if this would be valuable, or if the thought is that that actually should be an error.

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.