Giter Club home page Giter Club logo

Comments (69)

jonleighton avatar jonleighton commented on August 19, 2024

Hmm, this is very strange. Possibly related to #59, but I note that one of the co-ordinates is negative. That should never happen.

It would help a lot of you can share some code with me privately such that I can reproduce the issue myself.

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton I've pushed the failing scenario but I'm not happy with this code.

I think we should investigate which code on jQuery UI Datepicker is causing the issue.

Maybe is something related to "position calculator" where date picker do not appears outside of the document.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Thanks, that's really helpful. I can now reproduce the problem myself so I'll investigate it further in due course and try to figure out what's happening.

I should say that it might take me a few weeks to get round to it though.

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton take a look:

  2) FiscalActions create a new fiscal_action
     Failure/Error: within_tab 'Documentos oficiais' do
     Capybara::Poltergeist::ClickFailed:
       Click at co-ordinates [376, 317] failed. Poltergeist detected another element with CSS selector 'html body div#ui-datepicker-div.ui-datepicker.ui-widget.ui-widget-content.ui-helper-clearfix.ui-corner-all div.ui-datepicker-header.ui-widget-header.ui-helper-clearfix.ui-corner-all div.ui-datepicker-title' at this position. It may be overlapping the element you are trying to click.
     # ./spec/support/capybara.rb:20:in `click_link'
     # (eval):2:in `click_link'
     # ./spec/support/helpers.rb:87:in `block in within_tab'
     # ./spec/support/helpers.rb:86:in `within_tab'
     # ./spec/requests/fiscal_actions_spec.rb:46:in `block (2 levels) in <top (required)>'

In this case, poltergeist is right because the date picker remained open.

Maybe, before doing any action we should focus out the current element (that can be focused by a click or by a keyboard interaction like in fill_in).

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Thanks for the info. Maybe we should trigger a blur event after fill_in. That would presumably close the picker.

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton that sounds interesting for poltergeist in general but I guess will not fix the date picker issue.

The date picker closes when click in some element that is not the date picker itself or pressing tab on input.

I don't know why blur event is not used instead of intercepting tab key press and clicking outside.

Anyway, I will try it here on local copy of poltergeist :)

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton it already happens: https://github.com/jonleighton/poltergeist/blob/master/lib/capybara/poltergeist/client/agent.coffee#L151-166

I will try to implement a "fix" inside my project until we found the real problem.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Okay, but be aware that the current released version (0.6) doesn't have that code (for the blur event).

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

yep!

I'm using the master version because the keyboard events aren't handled on version 0.6 and that affects me :)

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton I found the offending line: https://github.com/jquery/jquery-ui/blob/90705cdffe58b0448a4520fef922ec7f28afd722/ui/jquery.ui.datepicker.js#L707

I don't know the reason yet :(

from poltergeist.

elisehuard avatar elisehuard commented on August 19, 2024

having the same error. At the very first element it tries to fill (which is not a date) it does:
Capybara::Poltergeist::ClickFailed:
Click at co-ordinates [-86, 658] failed. Poltergeist detected another element with CSS selector '' at this position. It may be overlapping the element you are trying to click.

I'm also using jQuery datepicker in my app. poltergeist HEAD and phantomjs 1.5.0 on OS X Lion.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

@elisehuard does your problem go away if you remove jQuery date picker?

Also, you could maybe try to just click elsewhere in the page before the fill_in. E.g. find('h1').click or something. Worth a try.

I do want to find time to properly look into this though, because it's fundamentally weird/wrong that it is showing a negative co-ordinate. That should never happen.

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton take a look http://bugs.jqueryui.com/ticket/8330 and http://bugs.jqueryui.com/ticket/8331

The first issue we have is: date picker do not close on blur event and seems like John don't want to do that in jquery ui and I'm not sure if it's a good thing.

The second issue is related to double focusing element.

Browsers works fine but something goes wrong on phantom.js.

If you could participate in discussion of these issues on jquery ui, would be great :)

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

@sobrinho it seems to me that we should solve this in poltergeist/phantomjs, not jquery.

Can you explain a bit more about the issue with double focusing? Perhaps you can provide a simple test case? (maybe even just a phantomjs script if the issue is in phantomjs...)

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

Typo: john => scott :P

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton surely, focus the input: http://jsfiddle.net/aCgJh/1/

The input receives a focus from user interaction (click), it opens the date picker and date picker trigger trigger focus again (note the input is already focused).

Every time you open the date picker, the focus event is called twice and should be called only once :(

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Ok, and have you worked out how this is affecting PhantomJS differently to other browsers?

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton not yet :(

from poltergeist.

elisehuard avatar elisehuard commented on August 19, 2024

@jonleighton I removed just the datepicker but kept the rest of jquery ui, and then removed jquery ui altogether. Both had the same effect, changing the error: still a negative position, not on the first field clicked, but on a button further on in the tests. Not the first button, but the second.

Failure/Error: click_button "Continue"
   Capybara::Poltergeist::ClickFailed:
     Click at co-ordinates [-86, 658] failed. Poltergeist detected another element with CSS selector '' at this position. It may be overlapping the element you are trying to click.

We have a fairly complex application, a wizard, sliding horizontally from form to form. It looks like the sliding is not happening (judging from the screenshot). We're using a jquery animate with a new position of the viewport (left: -1024), but screenshot shows we're still on the first form. It does fill in the appropriate fields (which have been preloaded, so are there), but when it tries to click 'continue', it fails with the error above.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

This should be fixed by the above commits. I haven't fully understood what's triggering it, but it basically looks like a rendering issue inside PhantomJS or (Qt)WebKit, and have managed to find a work around.

@elisehuard, can you confirm if this solves your issue?

from poltergeist.

elisehuard avatar elisehuard commented on August 19, 2024

very nice, does look like it solved the problem! Thanks!

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@jonleighton fixed the issue here too, thanks!!

from poltergeist.

elisehuard avatar elisehuard commented on August 19, 2024

oops, cheered too soon, it's not fixed after all

Click at co-ordinates [-88.5, 629] failed. Poltergeist detected another element with CSS selector '' at this position. It may be overlapping the element you are trying to click.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

nooooo.... damn. can you explain any more about what you're doing? you're also using the jquery date picker, right?

ccing @mortice which I am sure he'll appreciate ;)

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

I reckon I know what it is, at least roughly. Jon, we solved the issue
for some cases by resetting the scroll position before locating
elements to click on them, right?

In the app in question, the scroll position doesn't get changed, but
the left/right positioning of elements does, bringing them out
of/putting them into the viewport. So if I'm right, our fix doesn't
work, and we need to force webkit to render, or else find some clever
way of determining that elements have moved around.

Of course, I'm on a train and can't test this theory. But here's an
issue comment anyway. <3

On 6 Jun 2012, at 13:56, Jon Leighton
[email protected]
wrote:

nooooo.... damn. can you explain any more about what you're doing? you're also using the jquery date picker, right?

ccing @mortice which I am sure he'll appreciate ;)


Reply to this email directly or view it on GitHub:
#60 (comment)

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Okay, I should probably spend some time trying to figure this out in PhantomJS/QtWebKit really. Additional test cases will help if you can come up with them. Ta

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

I think this describes the issue:

rentalcustard@fcadd66

(On branch https://github.com/mortice/poltergeist/tree/issue-60)

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

I suck. Fixed the test: rentalcustard@d66c8a9

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

By the way, putting a sleep 1 before the click causes the test to pass, so this seems to be a thing about jQuery animations not having finished before Poltergeist tries to do stuff on the page. I have shit all clue what to do about that. Maybe something like this? But it looks jQuery-specific? http://stackoverflow.com/questions/724911/how-do-i-find-out-with-jquery-if-an-element-is-being-animated

from poltergeist.

levent avatar levent commented on August 19, 2024

@mortice @jonleighton I'm having exactly the same issue. We have a lightbox style modal and it seems to be trying to click a link on it before it has finished z-index'ing and animating in. With a sleep the test does pass.

The error:

Failure/Error: click_link 'Something Else'
Capybara::Poltergeist::ClickFailed:
  Click at co-ordinates [672, -93.5] failed. Poltergeist detected another element with CSS selector '' at this position. It may be overlapping the element you are trying to click.

I tried adding a JS method that appends the following class onto the html body:

.disable-animations * {
  -webkit-transition-duration: 0 !important;
  -moz-transition-duration: 0 !important;
  -ms-transition-duration: 0 !important;
  -o-transition-duration: 0 !important;
  transition-duration: 0 !important;
}

I'm trying to call that in my spec with:

page.evaluate_script("ourUIToolkit.disableAnimations();")

...but that did not help (although it does actually seem to disable the animations in Chrome)

Am using HEAD of master

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

@levent Ha, I didn't know you were an actual Poltergeist user as opposed to avid #poltergeistconf attendee ;)

Okay so based on the above I think that Poltergeist needs some way for click operations to play nice with Capybara's retry mechanism (you know, the thing that keeps trying if the thing you need is not on the page yet). I think that should solve it.

from poltergeist.

levent avatar levent commented on August 19, 2024

Fo shiz!!


So the culprit seems to be in Capybara's lib/capybara/node/base.rb where there is this synchronize method which may also be known as wait_until:

def synchronize(seconds=Capybara.default_wait_time)
  retries = (seconds.to_f / 0.05).round

  begin
    yield
  rescue => e
    raise e unless driver.wait?
    raise e unless driver.invalid_element_errors.include?(e.class) or e.is_a?(Capybara::ElementNotFound)
    raise e if retries.zero?
    sleep(0.05)
    reload if Capybara.automatic_reload
    retries -= 1
    retry
  end 
end

Anyway capybara-webkit would raise a Capybara::ElementNotFound instead of a Capybara::Poltergeist::ClickFailed causing the retry to happen.

I'm not sure if a driver is only supposed to raise those or add all its retry-able exceptions into the invalid_element_errors array?

That or is_a?(Capybara::ElementNotFound) seems smelly to me.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Ya, we currently have just Capybara::Poltergeist::ObsoleteNode in invalid_element_errors. Maybe just adding ClickFailed will solve the problem. Perhaps somebody can try :)

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

Doesn't look like it - my spec still fails. At the risk of coming across as exceedingly negative (I know, never happened before...) that Capybara code stinks to me. Using exceptions for flow control, checking on class, magic numbers... yuck.

I'd like to avoid relying on that code. Am I going to have to hack Capybara as well now? Is there any end to this rabbit hole of eternal pain?

from poltergeist.

levent avatar levent commented on August 19, 2024

@mortice my spec passed though I agree it's a bit of a mess.

On the bright side, I hear #poltergeistconf ends with a wicked party with balloons and dancing.

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

Oh, hold that thought. Setting Capybara.default_wait_time to something other than 0 in the spec suite and adding the exception to the invalid_element_errors method causes the test to pass. It makes Poltergeist's test suite quite a bit slower though (where by 'quite a bit slower', I mean 'own-eye-removingly slower'). And it robs me of the opportunity to rage on another project. Anyway, you can check out the horror: https://github.com/mortice/poltergeist/tree/issue-60

I suspect the use of exceptions for flow control in this case is too deeply ingrained in Capybara and its drivers to get any change approved. But perhaps we could look at having drivers expose to Capybara the information that they're ready to assert on (no js executing, no animations, etc.) so it doesn't try to assert and have to rescue/retry in this frankly horrible way? That shouldn't be backward-incompatible and it's something we could implement our end, right?

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

@mortice For a "real" test suite, you would never be doing anything where "success" is exceeding the wait time. So I think we could legitimately just set the wait time in this one specific test in our suite, to keep things fast. But I don't think adding ClickFailed to the invalid_element_errors will adversely affect real suites.

Regarding, this:

But perhaps we could look at having drivers expose to Capybara the information that they're ready to assert on (no js executing, no animations, etc.) so it doesn't try to assert and have to rescue/retry in this frankly horrible way? That shouldn't be backward-incompatible and it's something we could implement our end, right?

Not sure I understand. Please elaborate?

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

Oh, and while I'm ranting about this to anyone who'll listen: my test only passes when you run it individually. When you run the whole test suite on that branch, it fails for me. This suggests that phantomjs is slowing down as it runs for longer, or something, and hence what should be obvious from looking at the code: retrying based on a time limit is not deterministic. If that's the right word. I'm too angry to check.

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024
For a "real" test suite, you would never be doing anything where "success" is exceeding the wait time.

Unless you're running an animation which takes a long time and wanting to do something when that animation finishes?

Not sure I understand. Please elaborate?

What I'm suggesting is rather than:

begin
  driver.try_something
rescue
  #lots of checking conditions, sleeping and possibly retrying
end

Capybara should do something like:

begin
  driver.waiting_until_ready do
    driver.do_something
  end
rescue
  #if we get here, no point retrying because the driver has already told us things won't change
end

Even better would be:

driver.do_something #and let the driver manage any retrying, checking if ready.

But this last one won't be backwards-compatible, whereas introducing a waiting_until_ready method and only using it if available would be.

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Unless you're running an animation which takes a long time and wanting to do something when that animation finishes?

I said "exceeding". If you exceed the wait time, that means an exception is thrown by Capybara, hence the test fails (unless you catch the error, which you would only want to do in the test suite for Capybara or one of its drivers...)

The problem with your suggestion is how do you define ready_to_act?. It's a semantic question for the user of the library, not the author of the driver. For example I as a driver author don't know what animation library you might be using, or whether animations on the page are even relevant to a given test you've written passing or failing...

So the polling that Capybara does is designed to prevent the Capybara user from having to add explicit synchronisation in their code. We can certainly comment on the quality of the implementation, but I think the feature in general is pretty useful...

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

I understand where you're coming from Jon, I just don't agree that the feature in Capybara is worth the consequences, for reasons I'll explain when we have another caffeine-fuelled day of hacking and raging.

In the mean time, I'm going to merge my issue-60 branch once I've isolated the default_wait_time manipulation to the test case for this issue. Cool?

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Seems good :)

from poltergeist.

levent avatar levent commented on August 19, 2024

@mortice here's a horrendous spec that I botched together:
https://github.com/levent/poltergeist/compare/feature/use_capybara_retry_mechanism

I was trying to add a function on element #two that would remove it onclick so it's not overlapping #one on the second retry. The onclick function just wouldn't trigger though.

from poltergeist.

levent avatar levent commented on August 19, 2024

...beat me to it

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

Oh hey guess what? This won't work in Capybara 1.0, which we support, because none of the aforementioned code is in that version. Suggestions pl0x?

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

(See https://github.com/jnicklas/capybara/blob/master/History.txt#L60)

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

Just had a look through the 1.0 code and can't see an obvious solution. I suggest we drop 1.0 support.

from poltergeist.

rentalcustard avatar rentalcustard commented on August 19, 2024

Invisible Internet hug

On 8 Jun 2012, at 14:05, Jon Leighton wrote:

Just had a look through the 1.0 code and can't see an obvious solution. I suggest we drop 1.0 support.


Reply to this email directly or view it on GitHub:
#60 (comment)

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

I've remove Capybara 1.0 from the CI and the build now passes. I consider this bug fixed, but we can reopen if anyone disagrees.

from poltergeist.

lucascaton avatar lucascaton commented on August 19, 2024

In Rails 3.2.7 (released yesterday), this issue has happened again.

I'm using: capybara (1.1.2), poltergeist (0.7.0) and phantomjs (1.6.1).
In Rails 3.2.6, no spec fails. But in Rails 3.2.7, I got this error:

Failure/Error: click_button 'save_button'
   Capybara::Poltergeist::ClickFailed:
     Click at co-ordinates [360, 517.5] failed. Poltergeist detected another element with CSS selector 'html body div#ui-datepicker-div.ui-datepicker.ui-widget.ui-widget-content.ui-helper-clearfix.ui-corner-all table.ui-datepicker-calendar tbody tr td a.ui-state-default' at this position. It may be overlapping the element you are trying to click.
   # (eval):2:in `click_button'
   # ./spec/integration/entries_spec.rb:37:in `block (2 levels) in <top (required)>'

Anyone else with this issue?

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@lucascaton you should disable date picker for test environment because the date picker do not close when the input lost the focus (blur).

I reported two issues to jQuery UI but seems like they haven't much interest in fixing issues, take a look here and here.

Maybe you can try to argue there, I just gave up and disabled the date picker on my test environment :)

from poltergeist.

lucascaton avatar lucascaton commented on August 19, 2024

How did U disable that?

from poltergeist.

sobrinho avatar sobrinho commented on August 19, 2024

@lucascaton something like that:

  $('input[data-datepicker]').live('focus', function () {
    var element = $(this);

    if (environment !== "test") {
      element.datepicker();
    }

    element.mask('99/99/9999');
  });

from poltergeist.

lucascaton avatar lucascaton commented on August 19, 2024

But why in the Rails 3.2.6 all work?

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

There was some regression in 3.2.6 where RAILS_ENV doesn't get set correctly, I think. Don't know if that is related.

from poltergeist.

perrro avatar perrro commented on August 19, 2024

Related error here:

Failure/Error: Unable to find matching line from backtrace
Capybara::Poltergeist::ClickFailed:
Click at co-ordinates [994.5, 11] failed. Poltergeist detected another element with CSS selector 'html body#campaigns_current.body_client/campaigns div.cont_messages div.notice' at this position. It may be overlapping the element you are trying to click.

I can pass the test in debug mode, but not in silent mode.
There is an open calendar above the button, but its not overlaping.

sleep 5
page.driver.render("#{Rails.root}/tmp/capybara/#{Time.now.to_i}.png", :full => true)
find_button("Publish "#{@camp.name}"")
find_button("Publish "#{@camp.name}"").click

and the test fails on click

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

@Perro could you please open a new issue and include a screenshot?

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

sorry, that should be @perrro

from poltergeist.

darthdeus avatar darthdeus commented on August 19, 2024

Is there any way to work around this when I know the elements are overlapping but I just want to click anyway?

from poltergeist.

jonleighton avatar jonleighton commented on August 19, 2024

@darthdeus node.trigger('click') should work for that

from poltergeist.

perrro avatar perrro commented on August 19, 2024

Thank you, it is working now 👍

from poltergeist.

bswinnerton avatar bswinnerton commented on August 19, 2024

Where should node.trigger('click') be placed in the context of the test?

from poltergeist.

route avatar route commented on August 19, 2024

@bswinnerton instead of click

from poltergeist.

osfritsch avatar osfritsch commented on August 19, 2024

👍 node.trigger('click')

from poltergeist.

chetstone avatar chetstone commented on August 19, 2024

I'm running into this issue with poltergeist 1.5.1, rails 3.2.19. This is a simple query-UI dialog box, no date picker or automation that I know of. Adding a call to sleep between the click and the check sometimes makes the problem go away but not always. So how do you spell node.trigger('click') in the Capybara DSL? Right now I have click_button("Create User").

from poltergeist.

yaauie avatar yaauie commented on August 19, 2024

@chetstone it is my understanding that clicking the button just clicks the button and immediately returns control to your tests; if you want to determine the outcome of a click, you have to wait for it to happen.

Related: my comments on timing and control-flow on #504

We've received a lot of issues around this behaviour, and I would gladly accept a pull-request to add the ability to click-and-wait-for-all-effects, so long as it is opt-in and doesn't break current expectations.

from poltergeist.

chetstone avatar chetstone commented on August 19, 2024

So I've found the answer to one question. node.trigger('click') in my capybara spec is spelled find_button("Create User").trigger("click"). And that gets rid of the overlapping elements issue. But there's still the timing issue, if it is a timing issue. I set a ridiculously long 10 second wait time between triggers and I still get a failure about half the times I run the test (and it passes other times.) For example, this code:

within("#pkg-form") do
  fill_in 'Name', :with => '4g'
  sleep 10
  expect{
    sleep 10
    find_button("Create Package").trigger("click")
    sleep 10 
  }.to change(Package, :count).by(1)
end

will about half the time get this error:

 Failure/Error: expect{
   count should have been changed by 1, but was changed by 0

And by the way, the log shows that the item was created in the database, but capybara didn't pick up the change in count. And this error never pops up when running with selenium.

from poltergeist.

chetstone avatar chetstone commented on August 19, 2024

Oops. Having used selenium a bit more, I do see that error, but much less frequently, and it is easily suppressed with a short ( 0.2 sec ) sleep time. So perhaps this is a capybara issue that poltergeist happens to stumble over more frequently. I suspect it also has to do with the jquery-ui dialog box the button is in.

from poltergeist.

narendra-chandratre avatar narendra-chandratre commented on August 19, 2024

Its still failing for me :( Unable to click with success ! Help

from poltergeist.

Related Issues (20)

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.