acvetkov / sinon-chrome Goto Github PK
View Code? Open in Web Editor NEWTesting chrome extensions with Node.js
License: ISC License
Testing chrome extensions with Node.js
License: ISC License
I'm having trouble making sinon-chrome stubs work with sinon.match
.
I use webpack, karma, mocha and sinon-chai. The spec below may reproduce the error.
It looks like sinon-chrome's stub doesn't recognize sinon.match
and treats it like a normal object. The error is "AssertionError: expected stub to have been called with arguments hasOwn("key")%D", while it should be "arguments matching hasOwn("key")%D".
Any idea what went wrong?
describe('Sinon Native Stub', function () {
it('calledWithMatch + match', function () {
const stub = sinon.stub()
stub({key: 'value'})
stub.should.be.calledWithMatch(sinon.match.hasOwn('key'))
})
it('calledWith + match', function () {
const stub = sinon.stub()
stub({key: 'value'})
stub.should.be.calledWith(sinon.match.hasOwn('key'))
})
it('withArgs + match', function () {
const stub = sinon.stub()
stub({key: 'value'})
stub.withArgs(sinon.match.hasOwn('key')).should.be.calledOnce
})
})
describe('Sinon Chrome Stub', function () {
it('calledWithMatch + match', function () {
chrome.storage.local.set({key: 'value'})
chrome.storage.local.set.should.be.calledWithMatch(sinon.match.hasOwn('key'))
})
it('calledWith + match', function () {
chrome.storage.local.set({key: 'value'})
chrome.storage.local.set.should.be.calledWith(sinon.match.hasOwn('key'))
})
it('withArgs + match', function () {
chrome.storage.sync.set({key: 'value'})
chrome.storage.sync.set.withArgs(sinon.match.hasOwn('key')).should.be.calledOnce
})
})
Results:
Sinon Native Stub
√calledWithMatch + match
√calledWith + match
√withArgs + match
Sinon Chrome Stub
√calledWithMatch + match
×calledWith + match
AssertionError: expected stub to have been called with arguments hasOwn("key")%D
×withArgs + match
AssertionError: expected stub to have been called exactly once, but it was called 0 times
Hey,
thanks a lot for this repo. It really helps.
One question: Is there actually a way to test event listeners on the port object. How would one test the following code?
Chrome.runtime.onConnect.addListener(function(port) {
port.onDisconnect(function() { console.log('Port disconnected'); });
});
Cheers.
Clemens
I forked the project and tried to run the usage example but the second test is failed at assert.calledOnce(chrome.browserAction.setBadgeText);
. The callback in chrome.tabs.query(params, callback);
isn't invoked.
Here is my fork: https://github.com/phongvis/sinon-chrome with the following changes:
test-background
option for npm-run
and install jsdomexamples/src
examples/background.test.js
also in examplesCould you have a check? Thanks.
Hello. First of all, thank you for a great util for testing chrome API related code.
But I don't use phantom in my tests. That's why I ask you to remove PhandomJS peer dependency from your package.json - I don't want to store it.
I get undefined
when I use chrome.storage.sync.QUOTA_BYTES_PER_ITEM
, or any other sync
properties.
Version 0.1.1 from npmjs is broken. It throws the following error when it is executed:
module.js:338
throw err;
^
Error: Cannot find module './chrome-event'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:278:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at /path/to/package/node_modules/sinon-chrome/chrome.js:91:23
at Object.<anonymous> (/path/to/package/node_modules/sinon-chrome/chrome.js:865:2)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
The package.json is different from the one here in github. The main property value is "chrome.js" instead of "src/chrome.js". This file exists. But, as the error shows, it doesn't find the chrome-event module in the root folder. The chrome-event module is inside the src folder.
Version 0.1.0 doesn't have this problem.
Couldn't find anything related in the examples, but how can I overcome this situation?
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
// [..]
chrome.runtime.sendMessage({
// [...]
});
});
I want to spy chrome.tabs.query callback.
According to your readme, the schema for WebExtensions bases on Firefox 49. However, the current stable version is 55. Please consider updating to Fx55.
Hi,
I am using Sinon-Chrome to test a Chrome extension. One of the functions is that user can highlight text on a web page. This is how I think I can test this with Sinon-Chrome:
<mark>
.I think I can do step 1, but don't know how to do step 2 or 3 if I don't want to open a real URL in browser. How to give the Chrome extension a DOM to update (and then check) without open an actual website?
Ideally such a (virtual?) DOM can be loaded from a pre-saved file, so 1) it will be exactly the same every time, and 2) it makes the test synchronous (open a real URL will be asynchronous).
Hi! How to set permisssionLevel for notifications?
I need to test this method:
export const notifyMessage = (payload): void => {
const { hashId, date, messageId } = payload;
chrome.notifications.getPermissionLevel((permissionLevel) => {
console.log('permissionLevel: ', permissionLevel);
if (permissionLevel === 'granted') {
chrome.notifications.create(`${hashId}`, options, (id) => {
console.log('notificationId: ', id);
});
}
});
};
and test:
describe('Notifications tests', () => {
beforeAll(() => {
global.chrome = chrome;
});
it('notifyMessage', () => {
notifyMessage(mockEmail);
expect(chrome.notifications.getPermissionLevel.calledOnce).toBeTruthy();
});
afterAll(() => {
delete global.chrome;
});
});
I don`t understand why getPermissionLevel return 'denied'(((
Plss help!
I am fairly new to (Chrome extension) testing and started with Jasmine (https://jasmine.github.io/). Then I realised that I need to 'stub' out many Chrome API functions for testing and found sinon-chrome, which is great. Is it possible to use sinon-chrome together with jasmine (and how?), or you have to choose one between sinon and jasmine?
Hello,
I'm not sure to understand everything yet but I'm currently trying to write test on my webextension using sinon-chrome and I got difficulties because it stubs browser.runtime.connect()
to undefined where browser.runtime.connect()
returns a runtime.Port
which contains event and methods.
A workaround like this is working for a test file when I'm testing if thing arrives on the event
import sinon from 'sinon';
import ChromeEvent from 'sinon-chrome/events';
export default () => {
return {
onMessage: new ChromeEvent(),
onDisconnect: new ChromeEvent(),
postMessage: sinon.stub()
};
};
describe("sidebar", function() {
it("should register a listener on sidebar", function() {
let port = Port();
port.name = "sidebar";
port.onMessage.addListener = sinon.stub();
onConnectListener(port);
sinon.assert.calledOnce(port.onMessage.addListener);
});
});
But on another test file I don't manage to get it to work and I don't really understand how I'm supposed to do.
Here is my method
const port = browser.runtime.connect({name: "worker"});
export function runTest(testObj, id, rootElement) {
// Only run the test suite if there's a root element
// (e.g. when in source view there's no root element set)
if (rootElement) {
let contentTest = testObj.check(rootElement);
testObj.errors = contentTest;
/* TODO: Follow progress on bug https://bugzilla.mozilla.org/show_bug.cgi?id=1370884 */
port.postMessage({
type: "processTestResult",
test: JSON.stringify(testObj),
id
});
}
}
And here is my "test"
describe("runTest", function(){
it("should postMessage on port", function(){
let port = Port();
let testObj = {
check: (any) => true,
errors: "There is no errors"
}
runTest(testObj, 0, true);
sinon.assert.calledOnce(port.postMessage);
});
});
Javascript wise, I'm pretty sure there is an issue with scope but I don't really have any idea about how to do in an other way.
My experience with testing is very limited (and considering how important it is, I'm kinda sad about it), sorry if it's a very simple question.
It seems chrome.js not in sinon-chrome folder, where I can find this file?
page.injectJs(node_modules + 'sinon-chrome/chrome.js');
I need it to test chrome extension. Thanks for any help~
I'm testing with Jest 19.0.2, and when I try to use:
chrome.storage.local.get(key, val => console.log(val))
It will never actually execute the anonymous function and log anything. Is this expected behavior?
I am not sure exactly how to actually trigger a connection using sinon-chrome.
Here is my test:
const browser = require('sinon-chrome/webextensions');
const sinon = require('sinon');
it("multiple content scripts can connect to the same background script", () => {
let onConnect = sinon.spy();
browser.runtime.onConnect.addListener(onConnect);
browser.runtime.connect(null, { name: 'one' });
browser.runtime.connect(null, { name: 'two' });
browser.runtime.onConnect.trigger();
browser.runtime.onConnect.trigger();
assert(onConnect.callCount === 2, 'on connect has been called 2 times');
});
This seems to work but I am not sure why. I was expecting that I don't need to call browser.runtime.onConnect.trigger();
What is the best way to improve documentation? I have a hard time using sinon-chrome
as a new user.
When I try to require the new version 1.0.0
with webpack I get the following error.
TypeError: 'undefined' is not an object (evaluating 'modules[moduleId].call')
I am currently learning to test my extension using Jasmine following this setup, which doesn't require node.js:
https://gist.github.com/stevenqzhang/333fd0b2bca201aabaa40c7b63a74296
All the sinon-chrome examples seem to run test using node.js. Is it possible at all to run sinon-chrome test without node.js? If so, any example will be great.
Thanks,
const chrome = require( 'sinon-chrome' );
const chai = require( 'chai' );
chai.use( require( 'sinon-chai' ) );
const expect = chai.expect;
expect( chrome.storage.sync.get ).not.to.equal( chrome.storage.local.get ); // fails, these are equal
expect( chrome.storage.sync.get ).not.to.have.been.called;
expect( chrome.storage.local.get ).not.to.have.been.called;
chrome.storage.sync.get( 'test' );
expect( chrome.storage.sync.get ).to.have.been.called;
expect( chrome.storage.local.get ).not.to.have.been.called; // fails
I found this after hours of trying to figure out why my test was failing where I was testing that my extension loads from sync storage and not from local storage.
First, thanks so much for making this! I was in the process of mocking all the chrome.* bits that I needed, but it looks like you've already done that! Much thanks. 😸
Second, I wondered if you could add a LICENSE
file and/or license
declaration in the package.json
file. Without that--at least in the US--this library is essentially All Rights Reserved.
MIT, BSD, or Apache are pretty fabulous for this sort of project. sinon
itself is BSD-3-clause. karma-sinon-chrome
(which wraps this library) is MIT. It'd be super helpful to have one selected for this library also (see "none license" https://www.npmjs.com/package/sinon-chrome)
It looks like you've used the MIT before, so I'll assume (for now) that's where this is headed. 😉 But a license statement would help for sure. 😄
Thanks! 🎩
The link to the pre-built sinon-chrome.js
in the README is no longer valid.
Would it be possible to include a final sinon-chrome.js
file in each published npm module? Right now I'm finding it tricky to have consistency with sinon-chrome.js
in both my Node.js and and PhantomJS tests. It would be very convenient to use the same npm install for both environments without having to run webpack on my own.
Hi,
I am working on a chrome extension that requires user to sign in and using hello.js to handle the authentication with different oauth services. So far I am only using google+ authentication because this is a chrome extension and user should have a google account.
I want to 'mock' the google+ authentication service using sinon-chrome, so the extension does not have to communicate with google+ during the test. I can see two problems:
Thanks,
Hi,
I've been using sinon-chrome 0.2.1 with PhantomJS 2.0.0 on node v0.12.6 and I got stuck on an issue where PhantomJS silently ignored chai's assertion errors, i.e. tests were always successful...
Fortunately, I've been able to fix it by overriding a function evaluate
in a webpage object created by phantomjs but I'm not sure if it is a right resolution.
Please review my workaround when you have time. Any suggestion is appreciated.
The gist is the workaround (deriving from beforeeach.js), adding code snip from line 8 to 43. I modified the function wrapper string at line 42. You can find the original code in phantomjs webpage.js.
Other test-use dependencies are:
Any plan to add Apps features? For example: https://developer.chrome.com/apps/fileSystem
I've read the examples and everything else but I'm still confused on how to use sinon-chrome.
The extension I'm building has a lot of communication between content and background scripts.
For example, when a user access some webpage (defined in my match rules), the extension icon must become active. Moreover, if the icon is clicked, a sidebar should open.
Currently, I'm trying to do something like this:
global.chrome = require('sinon-chrome');
describe('chrome.*', function () {
global.chrome = {
browserAction: {
setIcon: {
get: jasmine.createSpy('get'),
set: jasmine.createSpy('set')
}
}
};
beforeEach(function () {
spyOn(chrome.browserAction, 'setIcon');
chrome.tabs.create({ url: 'http://www.customdomain.com' });
});
it('tracks chrome.tabs.onUpdated events', function () {
expect(chrome.browserAction.setIcon).toHaveBeenCalled();
console.log(chrome.browserAction.setIcon.callCount);
})
});
Am I misunderstanding something?
Should probably be added, it's a pretty useful one!
Possible?
Hey,
I'm trying to test my extension's popup code. The popup has a init function which catches data from the background page. In order to do that the popup sends a request to the background page via chrome.runtime.sendMessage( ... )
.
Now I tried different approaches how to 'fake' the response from the background page, currently I'm trying this approach.
But the the listener doesn't get called, once the Popup sends the request...
What am I doing wrong?
Hi!
I'm going to rewrite a library I wrote using sinon-chrome. It will make the tests so much better! However I was also hoping to use your chrome promise library 'then-chrome' - Would that be possible?
Here's a reduced test case: https://gist.github.com/arantius/33d318f57ced2f1b7ef5c49740b00e01
Try to use sinon-chrome, with browser
API. Fail. chrome
here works (well, doesn't crash before Karma initialization does, for this reduced case). Documentation claims both APIs are supported, but I can't tell how.
I ran it on my machine after an npm install and got this
$ npm test
> [email protected] test /Users/Stephen/Desktop/sinon-chrome/example
> phantomjs test/run.js
TypeError: 'undefined' is not a function (evaluating 'self.epilogue.bind(self)')
../node_modules/mocha/mocha.js:3980 in Spec
../node_modules/mocha/mocha.js:1822
../node_modules/mocha/mocha.js:6087
test/run.js:21
Hi, thank you for awesome module!
I have been trying to override a stubbed method provided by sinon-chrome with my implementation to simulate chrome.runtime.lastError
set inside the method.
Is there any officially-recommended way to override stubbed methods?
I'll write down here what I have tried for overriding methods just FYI.
First, I tried simply overwrite the method with a function by assignment as mentioned in README, but it seemed not working at all.
chrome.runtime.id = 'my_test_id';
chrome.runtime.getURL = function (path) {
return 'chrome-extension://' + chrome.runtime.id + '/' + path;
};
// FAIL (getURL() returns undefined)
assert.equal(chrome.runtime.getURL("test"), "chrome-extension://my_test_id/test");
This is because stubbed methods are defined by Object.defineProperty
with writable: false
.
Second, I tried sinon.stub()
to stub a stubbed method, which sounds complicated. :P
chrome.runtime.id = 'my_test_id';
sinon.stub(chrome.runtime, "getURL", function (path) {
return 'chrome-extension://' + chrome.runtime.id + '/' + path;
});
// Error
assert.equal(chrome.runtime.getURL("test"), "chrome-extension://my_test_id/test");
And sinon output error:
TypeError: Attempted to wrap undefined property getURL as function
Third, I tried replacing entire chrome.runtime
namespace object with another one.
chrome.runtime = {
id: "my_test_id",
getURL: function (path) {
return 'chrome-extension://' + chrome.runtime.id + '/' + path;
}
};
// PASS
assert.equal(chrome.runtime.getURL("test"), "chrome-extension://my_test_id/test");
Although this one could mange to override a namespace including target method, it looks weird and has too much side-effect which is not related to the test.
I don't think this one is ideal, and there should be another way to override stubbed methods easily IMHO.
The stubs currently don't return any value by default, which is fine in general, but connect/connectNative return a Port instance. It'd be nice if there was an easy way to get a prepared Port object, since this package already has much of the infrastructure for the events.
I'm writing some unit test for a chrome-extension and I was testing the function that uses chrome.i18n.getMessage()
. Each test passes smoothly at first but I have to skip the second test on the specific function.
.
But after testing my function by removing the skip
at line 57, that happens :
According to the Wiki about Cookie plugin, I assume the registered plugin must be removed after the test in order to restore the sinon stubs.
I tried the chrome.flush()
and delete chrome
, both didn't work.
** ❓ Does somebody know to do this ❓ **
Hi,
I am unable to understand run the examples in wiki page at it uses jsdom.env function, which is not supported by jsdom any more. Also, the wiki page example looks different from usage example, in readme.
Also how to test a plugin developed using https://github.com/HaNdTriX/webextension-toolbox ?
Can you please provide some suggestion ?
It would be convenient to have full example with extension and tests (similar to described here http://stackoverflow.com/a/26779746/740245)
When I invoke chrome.storage.local.get (string key, function callback)
, callback doesn't seem to be called. Is it supposed to be called?
Since 2.x the dist/ files don't appear to be in the releases when installing via npm. Was there a specific reason for this, or has this been missed?
Firefox is currently implementing web extensions - these are pretty much the same as the chrome.*
, although there are a few differences.
Firefox has created the browser.*
namespace which is virtually the same as the chrome.*
space. There are two differences:
browser.*
will gain Firefox specific extensions.browser.*
uses promises rather the callbacks.More information:
I can't get the sinon-chrome stubs to return when using promises. Any ideas??
The test itself:
var mocha = require('mocha');
var chai = require('chai');
var sinon = require('sinon');
var CookieFlip = require('../index');
describe("Cookieflip", function() {
beforeEach(function() {
global.chrome = require('sinon-chrome');
});
afterEach(function() {
global.chrome = {};
});
describe('cookieflip flow', function() {
it('Load the active tab', function(done) {
var dummyTabs = [];
dummyTabs.push({url: 'testurl1'});
dummyTabs.push({url: 'testurl2'});
dummyTabs.push({url: 'testurl3'});
chrome.tabs.query.withArgs({active: true, currentWindow:true}).yields(dummyTabs);
var cookieFlip = new CookieFlip();
cookieFlip.getCurrentTab()
.then(function(data) {
console.log('verify the new promise');
expect(data.url).to.equal('testurl');
done();
});
console.log('wait for the promise..');
});
});
});
Code to test:
var thenChrome = require('then-chrome');
function CookieFlip() {};
CookieFlip.prototype.getCurrentTab = function() {
return thenChrome.tabs.query({active: true, currentWindow: true})
.then(function(tabs){
return tabs[0];
});
};
module.exports = CookieFlip;
var chrome = require('sinon-chrome');
chrome.runtime.getUrl.returns('my-domain.com');
chrome.runtime.getUrl(); // my-domain.com
chrome.flush()
chrome.runtime.getUrl(); // undefined
But if we flush stubs, which has withArgs behavior, chrome.flush
does not work.
var chrome = require('sinon-chrome');
chrome.runtime.getUrl.withArgs(1).returns('my-domain1.com');
chrome.runtime.getUrl.withArgs(2).returns('my-domain2.com');
chrome.runtime.getUrl(1); // my-domain1.com
chrome.runtime.getUrl(2); // my-domain2.com
chrome.flush()
chrome.runtime.getUrl(1); // my-domain1.com
chrome.runtime.getUrl(2); // my-domain2.com
I know that there is a karma sinon-chrome wrap, but I could not find any reliable solution to what I'm looking for. I'm getting this error:
Chrome 52.0.2743 (Linux 0.0.0) ERROR
Uncaught TypeError: Cannot read property 'create' of undefined
at node_modules/sinon-chrome/dist/sinon-chrome.latest.js:7537
My spec file
describe('chrome.*', function () {
beforeEach(function () {
console.log(chrome);
});
it('should open a new tab', function () {
// chrome.tabs.create({});
// expect(chrome.tabs.create.called).toBe(true);
});
});
I installed sinon-chrome and karma-sinon-chrome via npm. My karma config file:
frameworks: [
'jasmine',
'requirejs',
'sinon-chrome'
],
// list of files / patterns to load in the browser
files: [
{ pattern: 'src/**/*.js', included: false },
{ pattern: 'test/*-spec.js', included: false },
'require.conf.js'
],
// list of files to exclude
exclude: [
'src/vendor/**/*.js'
],
// plugins
plugins: [
'karma-jasmine',
'karma-chrome-launcher',
'karma-requirejs',
'karma-sinon-chrome'
//'karma-coverage'
],
It seems like the Github project is published to NPM. require('sinon-chrome/extensions')
and require('sinon-chrome/webextensions')
break on v2.2.2.
And #69 is not correctly built.
It will be very conveniently If I can reset/resetBehavior all stubs in namespace scope.
For example
chrome.windows.reset();
is equals to
chrome.windows.get.reset();
chrome.windows.getCurrent.reset();
chrome.windows.getLastFocused.reset();
chrome.windows.getAll.reset();
chrome.windows.create.reset();
chrome.windows.update.reset();
chrome.windows.remove.reset();
and
chrome.windows.resetBehavior();
is equals to
chrome.windows.get.resetBehavior();
chrome.windows.getCurrent.resetBehavior();
chrome.windows.getLastFocused.resetBehavior();
chrome.windows.getAll.resetBehavior();
chrome.windows.create.resetBehavior();
chrome.windows.update.resetBehavior();
chrome.windows.remove.resetBehavior();
if I use
global.chrome = chrome
typescript gives me error error TS2304: Cannot find name 'global'.
but if I declare global like this
let global = {};
global.chrome = chrome
My tests will fail, because chrome
is not defined on the separate file that I am writing tests for.
Hi, I am new to Javascript testing. I have a chrome plugin and I want to write some unit tests to it.
I tried your "Usage example" but couldn't get the testing part to work. I don't know where to put the reference to the "sinon-chrome.latest.js". Also, how do I know if the tests are run? I am very confused on how sinon knows that it needs to run background.test.js and popup.test.js. And where can I see the test result?
Thanks
Hello. I'm using your awesome module to mock chrome application object in my tests and I've got an issue. Method chrome.runtime.getManifest() returns undefined, but there is something like this in my code: chrome.runtime.getManifest().version. I've tried to redefine getManifest method but It's not possible because of the descriptor of this property is:
Object.getOwnPropertyDescriptor(chrome.runtime, 'getManifest')
Object {set: undefined, enumerable: false, configurable: false, get: function}
configurable:false
enumerable:false
get:function get()
set:undefined
__proto__:Object
Is there a way to compel getManifest() return some objects?
Thanks in advance.
It would be good, if we have an example to test message passing. Most of the plugins have a postMessage and onMessage callbacks.
eg.
chromeobject.postMessage("hello")
chromeobject.onMessage.AddListener(function(data){
console.log(data)
})
A call to postMessage or message needs to trigger callback registered via onMessage.AddListener.
Currently there's no support for chrome.runtime.lastError
.
After importing sinon-chrome
what I'm doing is the following:
chrome.runtime.lastErrorStub = sinon.stub();
Object.defineProperty(
chrome.runtime, 'lastError',
{
get: chrome.runtime.lastErrorStub,
set: function(value) {
// TODO: maybe make the stub return this value
}
}
);
var originalChromeReset = chrome.reset;
chrome.reset = function() {
originalChromeReset();
chrome.runtime.lastErrorStub.reset();
chrome.runtime.lastErrorStub.resetBehavior();
}
Feel free to grab that code.
I am writing this issue out of desperation, I talked to seven developers to help with my goal testing a screen recording I am writing and none manged to help me with this. so here is the case.
I am building a screen recording and I am using Karma, Mocha, Sinon, and Sinon-Chrome to test it, I use Chrome APIs heavily desktopShare, Storage, gcm
. I followed the instructions of installation but I still get the following error:
Array
✗ should return -1 when the value is not present
undefined is not an object (evaluating 'chrome.app.runtime')
init@app/vendor/OneSignal.js:325:19
GT_internal_init@app/vendor/OneSignal.js:130:31
init@app/vendor/OneSignal.js:144:31
/tmp/app/scripts.babel/background.js:11:15 <- /tmp/d6dd7cd3b93245575010c03528a48fe4.browserify:28:15
Here is my test code
import sinon from 'sinon'
import chrome from 'sinon-chrome'
describe('Array', function() {
it('should return -1 when the value is not present', function() {
var background = require('../app/scripts.babel/background')
expect(background).to.exist
});
});
I made sure the karma-sinon-chrome
uses the latest version of sinon-chrome
, but I still get this error.
One strange thing I noticed that all the objects I get are empty objects inside chrome
namespace. I am so confused and I would really appreciate the help.
loadable = on "reload" no yellow box with error
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.