Giter Site home page Giter Site logo

testing-library / jest-dom Goto Github PK

View Code? Open in Web Editor NEW
4.3K 31.0 374.0 459 KB

:owl: Custom jest matchers to test the state of the DOM

Home Page: https://testing-library.com/docs/ecosystem-jest-dom

License: MIT License

JavaScript 84.88% TypeScript 15.12%
testing dom jest jest-matchers jsdom javascript custom-matcher react-testing-library dom-testing-library testing-library

jest-dom's Introduction

@testing-library/angular

Octopus with the Angular logo

Simple and complete Angular testing utilities that encourage good testing practices.


Read The Docs | Edit the docs



Build Status version downloads MIT License

All Contributors PRs Welcome Code of Conduct Discord

Watch on GitHub Star on GitHub Tweet

Open in GitHub Codespaces

Table of Contents

The problem

You want to write maintainable tests for your Angular components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down.

This solution

The @testing-library/angular is a very lightweight solution for testing Angular components. It provides light utility functions on top of Angular and @testing-library/dom, in a way that encourages better testing practices. Its primary guiding principle is:

The more your tests resemble the way your software is used, the more confidence they can give you.

Example

counter.component.ts

@Component({
  selector: 'app-counter',
  template: `
    <button (click)="decrement()">-</button>
    <span>Current Count: {{ counter }}</span>
    <button (click)="increment()">+</button>
  `,
})
export class CounterComponent {
  @Input() counter = 0;

  increment() {
    this.counter += 1;
  }

  decrement() {
    this.counter -= 1;
  }
}

counter.component.spec.ts

import { render, screen, fireEvent } from '@testing-library/angular';
import { CounterComponent } from './counter.component';

describe('Counter', () => {
  test('should render counter', async () => {
    await render(CounterComponent, { componentProperties: { counter: 5 } });

    expect(screen.getByText('Current Count: 5'));
  });

  test('should increment the counter on click', async () => {
    await render(CounterComponent, { componentProperties: { counter: 5 } });

    const incrementButton = screen.getByRole('button', { name: '+' });
    fireEvent.click(incrementButton);

    expect(screen.getByText('Current Count: 6'));
  });
});

See more examples

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's devDependencies:

npm install @testing-library/angular --save-dev

You may also be interested in installing jest-dom so you can use the custom jest matchers.

Docs

Version compatibility

Angular Angular Testing Library
17.x 15.x, 14.x, 13.x
16.x 14.x, 13.x
>= 15.1 14.x, 13.x
< 15.1 12.x, 11.x
14.x 12.x, 11.x

Guiding Principles

The more your tests resemble the way your software is used, the more confidence they can give you.

We try to only expose methods and utilities that encourage you to write tests that closely resemble how your Angular components are used.

Utilities are included in this project based on the following guiding principles:

  1. If it relates to rendering components, it deals with DOM nodes rather than component instances, nor should it encourage dealing with component instances.
  2. It should be generally useful for testing individual Angular components or full Angular applications.
  3. Utility implementations and APIs should be simple and flexible.

At the end of the day, what we want is for this library to be pretty light-weight, simple, and understandable.

Contributors

Thanks goes to these people (emoji key):

Tim Deschryver
Tim Deschryver

πŸ’» πŸ“– πŸš‡ ⚠️
MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ“–
Ignacio Le Fluk
Ignacio Le Fluk

πŸ’» ⚠️
TamΓ‘s SzabΓ³
TamΓ‘s SzabΓ³

πŸ’»
Gregor Woiwode
Gregor Woiwode

πŸ’»
Toni Villena
Toni Villena

πŸ› πŸ’» πŸ“– ⚠️
ShPelles
ShPelles

πŸ“–
Miluoshi
Miluoshi

πŸ’» ⚠️
Nick McCurdy
Nick McCurdy

πŸ“–
Srinivasan Sekar
Srinivasan Sekar

πŸ“–
Bitcollage
Bitcollage

πŸ“–
Emil Sundin
Emil Sundin

πŸ’»
Ombrax
Ombrax

πŸ’»
Rafael Santana
Rafael Santana

πŸ’» ⚠️ πŸ›
Benjamin Blackwood
Benjamin Blackwood

πŸ“– ⚠️
Gustavo Porto
Gustavo Porto

πŸ“–
Bo Vandersteene
Bo Vandersteene

πŸ’»
Janek
Janek

πŸ’» ⚠️
Gleb Irovich
Gleb Irovich

πŸ’» ⚠️
Arjen
Arjen

πŸ’» 🚧
Suguru Inatomi
Suguru Inatomi

πŸ’» πŸ€”
Amit Miran
Amit Miran

πŸš‡
Jan-Willem Willebrands
Jan-Willem Willebrands

πŸ’»
Sandro
Sandro

πŸ’» πŸ›
Michael Westphal
Michael Westphal

πŸ’» ⚠️
Lukas
Lukas

πŸ’»
Matan Borenkraout
Matan Borenkraout

🚧
mleimer
mleimer

πŸ“– ⚠️
MeIr
MeIr

πŸ› ⚠️
John Dengis
John Dengis

πŸ’» ⚠️
Rokas BrazdΕΎionis
Rokas BrazdΕΎionis

πŸ’»
Mateus Duraes
Mateus Duraes

πŸ’»
Josh Joseph
Josh Joseph

πŸ’» ⚠️
Torsten Knauf
Torsten Knauf

🚧
antischematic
antischematic

πŸ› πŸ€”
Florian Pabst
Florian Pabst

πŸ’»
Mark Goho
Mark Goho

🚧 πŸ“–
Jan-Willem Baart
Jan-Willem Baart

πŸ’» ⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!

Docs

Read The Docs | Edit the docs

FAQ

I am using Reactive Forms and the jest-dom matcher toHaveFormValues always returns an empty object or there are missing fields. Why?

Only form elements with a name attribute will have their values passed to toHaveFormsValues.

Issues

Looking to contribute? Look for the Good First Issue label.

πŸ› Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

See Bugs

πŸ’‘ Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a πŸ‘. This helps maintainers prioritize what to work on.

See Feature Requests

❓ Questions

For questions related to using the library, please visit a support community instead of filing an issue on GitHub.

Getting started with GitHub Codespaces

To get started, create a codespace for this repository by clicking this πŸ‘‡

Open in GitHub Codespaces

A codespace will open in a web-based version of Visual Studio Code. The dev container is fully configured with software needed for this project.

Note: Dev containers is an open spec which is supported by GitHub Codespaces and other tools.

LICENSE

MIT

jest-dom's People

Contributors

alexkrolick avatar allcontributors[bot] avatar brrianalexis avatar calebeby avatar connormeredith avatar dreyks avatar eps1lon avatar fpapado avatar gnapse avatar hiwelo avatar ianvs avatar jakeboone02 avatar jgoz avatar just-boris avatar kandros avatar lourenci avatar matanbobi avatar michaeldeboey avatar mufasa71 avatar nickmccurdy avatar r-walsh avatar re-taro avatar renatoagds avatar revathskumar avatar rubenmoya avatar sergicl avatar sheerun avatar simenb avatar skovy avatar smacpherson64 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jest-dom's Issues

Reformat README to use generic DOM selectors

Problem description:

The problem discussed in #47 was that the documentation is tightly coupled with dom-testing-library. End users may get confused, thinking jest-dom requires dom-testing-library selectors to work.

Suggested solution:

Update the README to use generic DOM selectors: document.querySelector in all examples.

Option 1:

Specific section for dom-testing-library:
Create a section discussing how to use it with dom-testing-library with examples and a link.

Option 2:

Each section could have examples for both:

Option 2: using <details> example

Example using document.querySelector
// 
test
const element = document.querySelector('.some-item'); expect(element)... // ...
Example using dom-testing-library
// 
test
expect(queryByText('test'))... // ...

Option 2: using direct example

Example using document.querySelector

// <div class="some-item">test</div>
const element = document.querySelector('.some-item');
expect(element)...

Example using dom-testing-library

// <div class="some-item">test</div>
expect(queryByText('test'))...

SVG elements fail on most matchers

  • jest-dom version: 1.5.1

  • node version: 8.11.3

  • npm (or yarn) version: yarn 1.7.0

  • dom-testing-library version: 2.7.0

  • react-testing-library version: 4.1.2

Relevant code or config:

expect(someSvgElement).toHaveClass("any-class");

What you did:

  • Make expect calls on SVG elements

What happened:

Exception thrown because they are not HTML elements.

Problem description:

Most assertions defined in this library would also be applicable to SVG elements, but they are being blocked unnecessarily.

Suggested solution:

Modify checkHtmlElement to allow elements that satisfy instanceof SVGElement.

I'm happy to open a PR if no one opposes.

toBeInTheDOM name is misleading about what it really does

As reported by @sompylasar in testing-library/dom-testing-library#9 .toBeInTheDOM is not really checking for what it name implies (because it does not have the concept of what "the DOM" is to being with). Right now is just a glorified .toBeInstanceOfClass(HTMLElement).

Refer to the original discussion for all suggested solutions. I'll mention here a few from there plus a new one:

// I kinda favor something like this (exact name is open for discussion)
expect(container).toContainElement(element)

// This makes me wonder if it only checks for direct parent-child relationship
// We could add it too, but not as a solution to this issue
expect(element).toBeAChildOf(parent)

// Keep .toBeInTheDOM allowing it to receive an optional element
// This still does not solve the problem when the container is not given, but I wouldn't rule it out
expect(element).toBeInTheDOM()
expect(element).toBeInTheDOM(container)

Create new matcher `toBeLabelled`

Describe the feature you'd like:

The idea is to have a custom matcher on the model of toBeRequired or toBeDisabled helping folks to know if they labelled correctly the markup they are testing.

This helper would be interesting for me because there is a variety of ways to label correctly an element, such as:

  • aria-label
  • aria-labelledby
  • alt on images
  • title on images and SVGs
  • having a text content (by using .toHaveTextContent)

The main limitation is that I am not sure we can easily know when a DOM node is labelled thanks to a nearby visually-hidden or displayed text which is not part of the same parent (but in this case, it would also be complex to find for screen readers/assistive technologies).

Suggested implementation:

Just doing all the tests decribed few lines before.

Describe alternatives you've considered:

Doing each test one after the other -or- using jest-axe but in this case lacking flexibility on doing more granular tests.

Teachability, Documentation, Adoption, Migration Strategy:

I could help with the implementation if you're up to adding this to this library πŸ‘

toHaveStyle ignores hover styles

Describe the feature you'd like:

I have a button that displays different styles when mouse moves over it:

background-color: green;
&:hover {
  background-color: red;
}

Here is my test:

fireEvent.mouseOver(button);
expect(button).toHaveStyle(`
  background-color: red;
`);

However, the test complained that the background color is still green instead of red.
I tried fireEvent.mouseEnter before calling mouseOver. Didn't make any difference.

I don't think it is fireEvent.mouseOver's problem. A onMouseOver event listener actually gets called when a mouseOver event is fired by fireEvent. Could it be a bug in jest-dom?

Describe alternatives you've considered:

So far, I commented out all test that verify hover styles. And I probably should leave this style test to visual/browser test?

"expect is not defined" when using with jest

  • @testing-library/jest-dom version: 4.0.0
  • node version: 12.8.0
  • npm (or yarn) version: 6.10.2

Relevant code or config:

Jest config

module.exports = {
  snapshotSerializers: ['jest-emotion'],
  setupFilesAfterEnv: ['./config/jest.js']
};

jest.js file

require('@testing-library/jest-dom/extend-expect');

What you did:

run the npm test

What happened:

Getting error expect is not defined ...

Determining test suites to run...

  ● Test suite failed to run

    ReferenceError: expect is not defined

      at Object.<anonymous> (node_modules/@testing-library/jest-dom/dist/extend-expect.js:7:1)
      at Object.newLoader [as .js] (node_modules/pirates/lib/index.js:104:7)
      at Object.<anonymous> (node_modules/@testing-library/jest-dom/extend-expect.js:2:1)

Reproduction:

https://github.com/tomitrescak/react-boilerplate/tree/Demo

Problem description:

I cannot run my tests

Suggested solution:

toHaveStyle inconsistency with colors

  • jest-dom version: 1.11.0
  • node version: 8.11.3
  • react-testing-library version: 4.1.4

Relevant code or config:

const { getByText } = render(
  <span style={{ backgroundColor: '#123456' }}>Hello World</span>
);
expect(getByText('Hello World')).toHaveStyle('background-color: #123456');
// The above assertion failed

What you did:

I rendered an element with a specific hex background color in its styles.

What happened:

I can't assert back that the background-color style is indeed there. This is because the actual styles I get back from the element give me the color in the rgb(r, g, b) format:

    expect(element).toHaveStyle()

    - Expected

    - background-color: #123456;
    + background-color: rgb(18, 52, 86);

Problem description:

The problem is that users are forced to use the rgb() format.

Suggested solution:

It'd be nice if toHaveStyle would convert hex colors to the rgb(r, g, b) format so this is transparent for users. Otherwise document the caveat and maybe provide the user with some alternative or direct them to a library they can use to make this conversion, and that they make sure they always use rgb(r, g, b) either directly or by converting their hex value dynamically themselves.

toHaveFormValues is not working on fieldsets

  • jest-dom version: 3.1.2
  • node version: v8.11.4
  • npm version: 5.6.0

Relevant code or config:

test('toHaveFormValues', () => {
  const { getByTestId } = render(
    <form data-testid="login-form">
      <fieldset data-testid="login-fieldset">
        <input type="text" name="username" value="jane.doe" />
        <input type="password" name="password" value="12345678" />
        <input type="checkbox" name="rememberMe" checked />
        <button type="submit">Sign in</button>
      </fieldset>
    </form>
  );

  const form = getByTestId('login-form') as HTMLFormElement;
  const fieldset = getByTestId('login-fieldset') as HTMLFieldSetElement;

  // passes
  expect(form).toHaveFormValues({
    username: 'jane.doe'
  });

  // fails with "toHaveFormValues must be called on a form or a fieldset"
  expect(fieldset).toHaveFormValues({
    username: 'jane.doe'
  });
});

What you did:

I tried to check form values with toHaveFormValues on a fieldset.

What happened:

The test fails "toHaveFormValues must be called on a form or a fieldset". It works well when running the assertions on the form element, though.

Reproduction:

Run the test.

Type definitions not properly loaded when importing from jest's setupTests

  • jest-dom version: 1.10.0
  • node version: 8.11.3
  • react-testing-library version: 4.1.4

Relevant code or config:

// package.json
  "jest": {
    "setupTestFrameworkScriptFile": "<rootDir>/src/setupTests.ts",
  },

// src/setupTests.ts
import 'jest-dom/extend-expect';

// src/components/SomeComponent/SomeComponent.test.ts
expect(element).toHaveTextContent('Hello World!');
// TypeScript error in the line above:
// Property 'toHaveTextContent' does not exist on type 'Matchers<void>'

Problem description:

When importing jest-dom/extend-expect, as instructed in the README, within jest's setupTestFrameworkScriptFile file, and using TypeScript at the same time, I get TypeScript errors in my test files saying that this library's custom matchers are not found:

Property 'toHaveTextContent' does not exist on type 'Matchers<void>'

However, when I import jest-dom/extend-expect from within the very text files that need those matchers it all works. Moreover, it even works if I import it in just one of those files, which suddenly removes the TS warning from a second test file, without having to import it again from that second test file.

Suggested solution:

This StackOverflow answer may be part of the solution, but I wanted to bring this up first to see if someone more knowledgeable with TypeScript can help. @jgoz maybe?

Better document toHaveTextContent's case sensitiveness

After having merged #72 I've realized the README is not clear about this, not even the examples hint at this, and they were even inadequate for how it behaved before this change.

toHaveTextContent documentation should be explicit about this. Maybe even mentioning that if someone wants it to behave as case-insensitive, they should use a regex with the i modifier (/some text/i) instead of a string.

@lourenci can you take this? I could but maybe you can tackle it before I can.

add .toHaveValue matcher

The problem

#65 implemented a high-level API for asserting values of an entire form, which is great. However, this API it does not allow to assert the value of a single form element, which is more desired is some scenarios

Describe the feature you'd like:

Add toHaveValue matcher (as described in the initial comment in #60) which can be used to assert value of a single form element - an input, select or textarea

expect(getByLabelText('Username')).toHaveValue('janedoe');

Suggested implementation:

Create toHaveValue(formElement, expectedValues) that calls existing getSingleElementValue (https://github.com/gnapse/jest-dom/blob/master/src/to-have-form-values.js#L38)

I will be glad to help with implementing this feature

Add toBeChecked for <input type="radio" /> and <input type="checkbox" />

Describe the feature you'd like:

I want this to work:

const input = document.createElement('input')
input.setAttribute('type', 'checkbox')
input.setAttribute('checked', true)
expect(input).toBeChecked()
input.setAttribute('checked', false)
expect(input).not.toBeChecked()

Describe alternatives you've considered:

expect(input.checked).toBeTrue()

Teachability, Documentation, Adoption, Migration Strategy:

This would need to be added to the docs like the rest of the assertions.

toContainHTML failure output is not useful

  • jest-dom version: 3.1.3
  • node version: v10.11.0
  • npm (or yarn) version: 6.9.0

Relevant code or config:

What you did:

const container = render(<SubmitButton>)
expect(container).toContainHtml('color: blue')

What happened:

 2019-04-25 at 3 27 53 PM

Reproduction:

Problem description:

The output failure message does not contain any useful information for tracking down the reason why it failed.

I have to convert it to something like expect(container.innerHTML).toContain('color: blue') to be able to debug it, making the custom matcher less efficient than just using the simpler builtin option.

Note, I saw theres a style matcher that could be used in this specific test, however the problem applies to any call to this matcher.

Suggested solution:

Pretty sure it just needs to change to cloneNode(true) at https://github.com/testing-library/jest-dom/blob/master/src/to-contain-html.js#L14 for it to print out all the nodes.

That fix would make it debuggable. To make it better than the output of toContain() it could be pretty-printed as indented and syntax highlighted html πŸ˜ƒ - any chance that has been considered or used by other matchers?

Here is the toContain() output for reference. You can imagine its much harder to debug a larger dom node

 2019-04-25 at 3 40 59 PM

Scoped package?

No pressure. I'm just wondering whether you've thought about moving to the scoped package format like the rest of the testing-library family of tools.

New toBeVisible custom matcher

As discussed in #4, this library needs a .toBeVisible custom matcher. It operates on an element, receives no extra arguments, and passes if the element is visible to the user.

expect(element).toBeVisible()

How?

This should be implemented by checking the element's computed style, and make sure that display is not none, and also visibility is not hidden or collapsed.

Why?

Doing the equivalent assertion using vanilla DOM APIs is cumbersome:

// Two assertions needed, both dealing with verbose APIs
expect(getComputedStyle(element).getPropertyValue('display')).not.toEqual('none')
expect(getComputedStyle(element).getPropertyValue('visibility')).not.toMatch(/(hidden|collapsed)/)

HtmlElementTypeError for custom jsdom instance

  • jest-dom version: 1.11.0
  • node version: 10.4.1
  • npm (or yarn) version: yarn 1.7.0

Relevant code or config:

describe('Index', () => {
  it('Suggests cities to search by', async () => {
    const { window } = await next.render('/')
    expect(window.document).toHaveTextContent('Warszawa')
  })
})

next.render is a helper I've created that returns custom jsdom instance

What you did:

Tried to use toHaveTextContent matcher with custom jsdom instance

What happened:

Error is thrown:

    received value must be an HTMLElement or an SVGElement.
    Received:
      object:

Reproduction:

As above

Problem description:

Problem description:

It seems you throw HtmlElementTypeError with htmlElement instanceof HTMLElement but the element that I pass has separate of HTMLElement created along separate window object.

See:

const { window } = new JSDOM(...)
console.log(window.document instanceof Document) # => false
console.log(window.document instanceof window.Document) # => true

Suggested solution:

  • Search for Document class in scope of passed container?
  • Use constructor.name, __proto__.constructor.name, __proto__.__proto__.constructor.name etc. instead of instanceof?

strange toHaveFocus() behaviour

Sorry for posting the question here, but I have tried spectrum.chat and SO without much success so far...

I'm having trouble understanding how toHaveFocus() works exactly. Here's my setup:

MyComponent.js

import React from 'react'
import styled from 'styled-components'

import TextArea from './TextArea'


const Container = styled.div`
  flex: 1;
  height: 100%;
  padding: ${props => props.theme.size};
`

const Title = styled(TextArea)`
  font-weight: bold;
  font-size: ${props => props.theme.sizeLarger};
  margin-left: ${props => props.theme.sizeSmall};
`

class MyComponent extends React.Component {

  handleTitleChange = e => {
    this.props.onTitleChange(e.target.value)
  }

  handleTitleLostFocus = () => {
    this.props.onChangeComplete()
  }

  render () {
    return (
      <Container>
        <Title 
          value={this.props.item.title || ''}
          onChange={this.handleTitleChange}
          onBlur={this.handleTitleLostFocus}
        />
      </Container>
    )
  }
}

export default MyComponent

MyComponent.test.js

import React from 'react'
import {render, fireEvent, prettyDOM} from 'react-testing-library'

import MyComponent from '../MyComponent'


describe('MyComponent', () => {
  it('handles title changes', () => {
    const title = 'title'
    const handleTitleChangeMock = jest.fn()
    const {getByText} = render(
      <MyComponent
        item={{
          title: title
        }}
        onTitleChange={handleTitleChangeMock}
        onChangeComplete={() => {}}
      />
    )
    const titleInput = getByText(title)
    console.log(prettyDOM(titleInput))
    fireEvent.click(getByText(title))
    expect(getByText(title)).toHaveFocus()
    fireEvent.change(getByText(title), {target: {value: title.slice(0, -1)}})
    expect(handleTitleChangeMock).toHaveBeenCalledTimes(1)
    expect(handleTitleChangeMock).toHaveBeenCalledWith(title.slice(0, -1))
  })
})

When I do this:

const titleInput = getByText(title)
console.log(prettyDOM(titleInput))

The console logs the following:

<textarea
    class="sc-htoDjs dLjZCT sc-bxivhb jdLTBU"
    style="height: 0px;"
  >
    title
  </textarea>

That textarea element is the one I am targeting. But then, when I do this:

fireEvent.click(titleInput)
expect(titleInput).toHaveFocus()

I get this error:

Received:
  <body><textarea style="min-height: 0 !important; max-height: none !important; height: 0px !important; visibility: hidden !important; overflow: hidden !important; position: absolute !important; z-index: -1000 !important; top: 0px !important; right: 0px;" /><div><div class="sc-bZQynM ePHCfO"><textarea class="sc-htoDjs dLjZCT sc-bxivhb jdLTBU" style="height: 0px;">title</textarea></div></div></body>

  at Object.it (src/__tests__/MyComponent.test.js:84:30)
      at new Promise (<anonymous>)
  at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
      at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)

I don't quite understand why when I'm trying to assert a textarea element toHaveFocus(), I'm receiving an error that references the entire DOM tree under body...

New toBeEmpty custom matcher

As discussed in #4, this library needs some sort of .toBeEmpty custom matcher. This will pass if the given element does not contain any child elements.

expect(element).toBeEmpty()

A few aspects of this are open to discussion. We'd like to come up with a different name that would be clearer and avoid name clashes with other matchers out there that might be checking emptiness of other things (e.g. array or collections of some sort).

How?

// TODO

Why?

Presumably doing the equivalent checks on one's own is not straightforward and concise enough.

Helper to attach a stylesheet to the document

Describe the feature you'd like:

This is prompted by this question on Twitter:

does toBeVisible in jest-dom take styles from CSS files into account? I'm checking a component that has a class that adds display: none; but expect(component).not.toBeVisible() is failing because it thinks the component is visible.

The problem, as I pointed out responding that tweet, is that when testing isolated components, css stylesheets that would normally be attached to the document via a <link /> element in the head area, are not attached to the virtual jsdom document in which the tests are being run.

Suggested implementation:

I'm not sure how this would be. Especially with css-in-js and css-modules in the picture, I'm not even sure if there's still a framework-agnostic way to automatically handle what these better css systems do with the css to dynamically generate a stylesheet.

Keeping it concrete, only considering stylesheets in general, I'm not even sure if we can make a helper load a css file. All I know is that we can attach css to the document having the actual css code as a string, as we already do here.

We can simplify the above providing some kind of helper to attach styles and run assertions with those styles on. It has to be some kind of wrapper that gives us the opportunity to clean up, because as you see in that test I linked to, the style element has to be detached and cleaned up after the test (something we're not even doing consistently in all those test cases 😱).

So at the very least I can come up with something like this:

const stylesheet = `
  .hidden { display: none }
`

// ...

test('...', () => {
  withStyles(stylesheet, () => {
    // ...
    expect(element).not.toBeVisible();
  });
});

Describe alternatives you've considered:

We can keep things as they are, but at the very least we need to document this better in the README.

If we keep things as they are, we can tell people to assert against the element having the css class name or not, but that kinda goes against the guiding principle. Because end users of web apps do not really care about the element having the class or not, but wether it is visible or not. Furthermore, with the popularity of css-in-js or even css-modules, people cannot rely on static css class names anymore.

Teachability, Documentation, Adoption, Migration Strategy:

TODO

.toBeVisible should consider "hidden" attribute

Describe the feature you'd like:

expect(element).toBeVisible() should return false if element.hasAttribute('hidden') unless it's been explicitly shown with styles (display && display !== 'none' for example).

Suggested implementation:

Add && !element.hasAttribute('hidden') here, plus a check on display:
https://github.com/gnapse/jest-dom/blob/238cc91bfaffa9dd5baed1b5a02d060909f7c30c/src/to-be-visible.js#L17-L22

Describe alternatives you've considered:

I'm using .toHaveAttribute("hidden"), but I feel like I'm testing an implementation detail.

New toBeEnabled() matcher

Describe the feature you'd like:

I'd like a matcher to check if a specific input element is enabled.

Describe alternatives you've considered:

Today, I check for the input being enable using the not.toBeDisabled() matcher. I think It would be better for the read/clarity of the test, I be able to write .toBeEnabled().

Discussion - extending matchers to handle NodeList

Describe the feature:

Would it make sense to extend the current matchers to handle NodeLists? Is there a need for this? I was thinking about queryAllBy* and querySelectorAll and wondering if it would be helpful to pass them directly to the matchers.

For example:

expect(queryAllByText('text')).toBeVisible();
expect(document.querySelectorAll('button')).toBeDisabled();

If all elements match the matcher, then it passes. If any of the elements do not match then it fails.

Descriptively assert that a form input/select/textarea has a given value

The problem

<select> elements, unlike input elements, do not have a value attribute. So there's easy no natural way to assert that a select element has a certain option selected. One would have to traverse through the options to see which one is selected.

To make it even worse, React makes it look like so, to the point that I got confused myself recently, when I spent more minutes that I would've liked trying to figure out why the following test (using react-testing-library) did not pass:

const { getByTitle } = render(
  <select title="Client status" value="archived">
    <option value="active">Active</option>
    <option value="archived">Archived</option>
    <option value="pending">Pending</option>
  </select>
);

expect(getByTitle('Client status')).toHaveAttribute('value', 'archived')

And to continue to make it even worse, the overall task may become more complex if using options grouped in <optgroup>s, or with multi-select elements.

Describe the feature you'd like

I started this issue thinking of suggesting a specific matcher to check a selected option in select elements. But while describing all of the above, I realize that it may be better to provide some generic way to check the value of form elements, regardless of them being inputs, textareas or selects (are there any other ones?).

Suggested implementation:

It could be providing assertions to work at the actual form input element level:

expect(userInputElement).toHaveValue('janedoe');
expect(passwordInputElement).toHaveValue('12345678');

or even at the form element level (identifying an input/select/textarea element by its name attribute):

expect(formElement).toHaveValue('username', 'janedoe');
expect(formElement).toHaveValue('password', '12345678');

It could be both use cases with the same matcher! And it could be created so that it would understand inputs, selects and textures (which are also different, their value is their child text content).

It could even be so that <select multiple> elements' values are arrays, and users could check at once the entire multiple selection (and maybe even part of it too??)

Describe alternatives you've considered:

select elements probably have some property at the dom level to check their value, instead of it being an attribute. I did not google for it, and do not have it at the top of my head, but if so, then expect(selectElement.value).toEqual(...) could help, but still it's not a generic solution for all kinds of form elements (or is it?)

dom-testing-library recently added the ability to getBySelectText, that allows users to select a select (pun not intended) by the text content of the option element within that select that is currently selected. This certainly helps, but it still leaves a weird not-so-expressive way to assert that a given select has a certain value selected:

expect(getByLabel('Client status')).toBe(getBySelectText('Archived'))

And even then, what happens if there are two selects that happen to have an option selected, both with the same text "Archived"?

And still this only addresses the problem with select elements.

Thoughts?

toContainElement should accept null or undefined

I got to this idea when I realized that is not always possible to negate .toContainElement:

expect(container).not.toContainElement(document.querySelector('.button'));

If indeed there's no element with class="button", the above will still fail. But not because the matcher finds the assertion to not be true. It fails because toContainElement does not allow null or undefined as argument.

I wanted to propose changing this matcher so that it will accept null and undefined.

toBeInTheDocument and toContainElement throws error if element is null

  • jest-dom version: 1.10.0
  • node version: 10.5.0
  • npm (or yarn) version: 6.2.0

Relevant code or config:

// downshift/src/__tests__/portal-support.js
const {getByTestId, queryByTestId} = render(
  <MyPortalAutocomplete />,
)
expect(queryByTestId('menu')).not.toBeInTheDocument()
getByTestId('button').click()
expect(getByTestId('menu')).toBeInTheDocument()

What you did:

Tried replacing toBeInDOM with any of the new suggested ways (toBeInTheDocument/ toContainElement )

What happened:

Both throws an error then the element is null

Reproduction:

↑ See relevant code or the Downshift repo https://github.com/paypal/downshift/blob/master/src/__tests__/portal-support.js#L57-L60

Problem description:

As far as I can tell there is no way to replace the current usage of toBeInTheDOM with the other functions. But I might be missing something?

Suggested solution:

I think they should accept falsy (or at least null) values and just return false if that's the case

Deprecate toBeInTheDOM in favor of toContainElement

Describe the feature you'd like:

It's been previously noted that toBeInTheDOM does not really perform the check that its name suggests (testing-library/dom-testing-library#9, #3). This was partially addressed in #25, where also toContainElement was introduced.

However, toBeInTheDOM continues to feel not right, at least for me. It now has two different behaviors: if it receives an element as argument, it'll check that the expect argument is contained within that extra element. If it does not receive an extra element as argument, it behaves as a glorified .toBeInstanceOf(HTMLElement), merely checking that the received expect argument is a DOM element, regardless of whether is contained anywhere.

Suggested implementation:

I propose that we remove toBeInTheDOM, maybe with a deprecation period.

Describe alternatives you've considered:

At the very least, we should update the documentation in the README about it. This current intro to this matcher is not accurate about what it does:

This allows you to assert whether an element present in the DOM container or not. If no DOM container is specified it will use the default DOM context.

There's no default DOM context (whatever that means). This matcher's only task when no DOM container is specified, is to assert that the given element is indeed an HTML (or SVG since recently) element.

Teachability, Documentation, Adoption, Migration Strategy:

We would need to update the documentation and provide users with alternatives moving forward:

One recommendation is to replace current uses with toContainElement.

Also, if users just want to check if an element exist, they can assert that what they have is not null or undefined. For instance, using dom-testing-library queries and regular jest matchers:

expect(queryByTestId('ok-button')).toBeTruthy();
expect(queryByTestId('ok-button')).toBeInstanceOf(HTMLElement);

Also, this would be a breaking change, so a major version bump is involved and users would have to explicitly update to get the change and be really forced to replace its uses.

passing a number to toHaveTextContent result in wrong error message

  • jest-dom version: 1.3.1
  • node version: 10.4.1
  • npm version: 6.1.0
  • dom-testing-library version: 2.6.4
  • react-testing-library version: 4.1.0

Relevant code or config:

expect(countSpan).toHaveTextContent(0);

What you did:

I should have passed a string to toHaveTextContent, but I passed a number.

What happened:

TypeError: matcher.test is not a function

Reproduction:

https://codesandbox.io/s/vjmp702z63
See tests/hello.js

Problem description:

The error message is misleading.

Suggested solution:

"TypeError" is fine, but the rest of the message should say something different.

<select> element value change is not recognized properly by toHaveFormValues

  • jest-dom version: 3.5.0

Relevant code or config:

const { container } = render(
  <form>
    <select name="priority">
      <option value="low">Low</option>
      <option value="medium">Medium</option>
      <option value="high">High</option>
    </select>
  </form>
)
const form = container.querySelector('form')
const select = container.querySelector('select')
fireEvent.change(select, { target: { value: 'high' } })
expect(form).toHaveFormValues({ priority: 'high' }) // <- fails here

The above test should pass, but it does not. It fails to recognize the change in the selected value of the select.

Problem description:

After some digging I'm pretty sure this has something to do with the cause of this issue in dom-testing-library. This issue was fixed in this PR, and this is mention in that PR description:

Since selectedOptions is not a reactive property, JSDOM was not updating to match the selected option in a select Element. The selected attribute is reactive.

We're using selectedOptions ourselves to check the selected options in a select. See the relevant code.

Suggested solution:

Maybe following the same approach as testing-library/dom-testing-library#124 and switch to use the select attribute instead.

Add .toBeInvalid and .toBeRequired

Describe the feature you'd like:

I was wondering if we could add toBeRequired and toBeInvalid as tests based on the same logic as toBeDisabled.

The toBeRequired test could be based on either having:

  • a required attribute;
  • an aria-required attribute.

The toBeInvalid test could be based on having:

  • an aria-invalid attribute.

For accessibility reasons, I am writing a lot of tests using these requirements and it would be way cleaner if I could use the same kind of syntax as toBeDisabled.
What are your thoughts about that?

Describe alternatives you've considered:

At the moment, I am using .toHaveAttribute('aria-invalid') or similar.

New toHaveStyle custom matcher

As discussed in #4, this library needs a .toHaveStyle custom matcher. It should receive an object of css properties and their values, and will pass if the element has all the css properties in that object with the expected values.

expect(element).toHaveStyle({
  backgroundColor: '#fff',
  height: '100%',
})

How?

This should be implemented to take advantage of window.getComputedStyle to obtain all the styles applied to an element. This includes styles acquired from css classes applied to it, as well as styles applied directly via the style="..." attribute.

Also, this probably would have to deal with supporting css properties specified in camelCase, and covert them to the "kebab-case" before comparing them to the actual styles. It'd be nice to do that without adding too many external dependencies if possible, or better yet, none at all.

Why?

Doing the equivalent check with vanilla DOM APIs would be a bit verbose. It's not just about checking the style=".." attribute, and decode information out of it (which by itself would be even more verbose), but it involves using the DOM api mentioned above. Also the fact that it'd enable users to check for multiple style properties at the same time makes it even more useful, and the alternative even more verbose.

For instance, the above example would be something like this:

expect(getComputedStyle(element).getPropertyValue('background-color')).toEqual('#fff')
expect(getComputedStyle(element).getPropertyValue('height')).toEqual('100%')

Media queries

First thank you for this awesome library!

I would like to use toHaveStyle to test a media query. I am migrating xstyled tests from jest-styled-components to jest-dom since the approach is better for me.

My question is simple. How to do the equivalent with toHaveStyle?

expect(container.firstChild).toHaveStyleRule('color', 'red', {
   media: '(min-width: 768px)',
})

add toContainQuerySelector matcher for better errors

Describe the feature you'd like:

Currently the recommendation for checking if an element exists is:

const htmlElement = document.querySelector('[data-testid="html-element"]')
const nonExistantElement = document.querySelector('does-not-exist')

expect(htmlElement).toBeInTheDocument()
expect(nonExistantElement).not.toBeInTheDocument()

(abridged from the docs)

But this returns pretty useless errors if the condition is not met. It would be much more useful to combine the querySelector with the existence check, such as:

expect(document).toContainQuerySelector('[data-testid="html-element"]')
expect(document).not.toContainQuerySelector('does-not-exist')

(this is also much shorter syntax)

This is comparable to toContainMatchingElement from the enzyme-matchers project.

Suggested implementation:

I've tried to match the code style of this project, but might have missed something:

import {matcherHint, printReceived, printExpected} from 'jest-matcher-utils'
import {checkHtmlElement} from './utils'

export function toContainQuerySelector(element, selector) {
  checkHtmlElement(element, toContainQuerySelector, this)
  return {
    pass: Boolean(element.querySelector(selector)),
    message: () => [
      matcherHint(`${this.isNot ? '.not' : ''}.toContainQuerySelector`, 'element', 'selector'),
      '',
      `Expected ${this.isNot ? 'no elements' : 'an element'} matching`,
      `  ${printExpected(selector)}`,
      'Received',
      `  ${printReceived(element)}`,
    ].join('\n'),
  }
}

Describe alternatives you've considered:

  • .not.toBe(null) or a hypothetical .toExist(), etc. have similar problems to .toBeInTheDocument: the returned error is not helpful for diagnosis because it does not include the content which was actually observed when an element is missing.

  • It might be valuable to be able to count the number of occurrences (e.g. toContainQuerySelector('foo', 4) to check for exactly 4 occurrences, but I can't think of a self-descriptive method name for this, so as-proposed this checks for 1-or-more, or exactly zero.

Teachability, Documentation, Adoption, Migration Strategy:

Recommendation can be updated to:

expect(document).toContainQuerySelector('[data-testid="html-element"]')
expect(document).not.toContainQuerySelector('does-not-exist')

No migration necessary; existing matchers do not need to change.

Codesandbox expect is not defined

  • jest-dom version: 3.1.3
  • react-testing-library version: 6.0.0

Relevant code or config:

https://codesandbox.io/s/ymjjk77x0z

What you did:

There are 2 files in the tests folder, one imports jest-dom and another does not.

ErrorFormatDateView.test.js Does import jest-dom and breaks by not finding the expect export.

FormatDateView.test.js Does not import, and using other matches can pass the test case.

Suggested solution:

jest-dom/extend-expect should export a default expect from jest.

Invitation to move to testing-library org

It's up to you, but if you'd like, you're welcome to transfer this repository to the testing-library organization on GitHub. This will give your project more credibility as part of the testing-library family of projects with a unified mission of tools which help people avoid testing implementation details.

Again, totally up to you. I just want you to know we appreciate all you've done and you're welcome to join us if you like.

Make it so the TypeScript definitions work automatically without config

If we follow the path we took in React Testing Library then that'll mean that people wont have to do anything fancy to make the typings/autocomplete show up which would be rad.

Specifically:

  1. Add testing-library__jest-dom to DefinitelyTyped
  2. Add @types/testing-library__jest-dom to @testing-library/jest-dom dependencies

I just tested it locally and that appears to work. If I have it in my node_modules then it just worksℒ️

Anyone up for this?

toHaveStyle not properly matching compound statement

  • jest-dom version: 2.1.0
  • node version: 8.9.4
  • npm version: 6.4.18
  • dom-testing-library version: 3.11.1
  • react-testing-library version: 5.2.0

Relevant code or config:

Copied & modified from your base CodeSandbox:

import React from "react";

const styles = {
  fontFamily: "monospace",
  textAlign: "center",
  transition: "opacity 0.2s ease-out, top 0.3s cubic-bezier(1.175, 0.885, 0.32, 1.275)"
};

export default ({ name }) => <h1 style={styles}>Hello {name}!</h1>;

Test:

test("react-testing-library works!", () => {
  const { container } = render(<Hello name="Jill" />);
  expect(container.firstChild).toHaveStyle(`font-family: monospace`);
  expect(container.firstChild).toHaveStyle(`text-align: center`);
  expect(container.firstChild).toHaveStyle(
    `transition: all 0.7s ease, width 1.0s cubic-bezier(3, 4, 5, 6);`
  );

What you did:

I was trying to test my transition style that's actually a compound statement.

What happened:

It seems toHaveStyle() will return true even if my assertion differs greatly. It does seem if I remove the compound statement in the test, it will properly fail:

  expect(container.firstChild).toHaveStyle(
    `transition: all 0.7s ease;`
  );

Reproduction:

https://codesandbox.io/s/14mlwzjjvj

Problem description:

I have two code paths (via props), one with transition, one without. I want to ensure the transition CSS is what it should be given the props input.

Suggested solution:

My one workaround for now is to put the transition in a separate class and include it based on my props, thus I can use toHaveClass().

Support async matchers?

Just a thought... Perhaps we could take advantage of the Jest 23 release and support custom async matchers. Something like:

expect(node).toEventuallyHaveTextContent('foo')

That would eliminate the need for using wait in dom-testing-library in many cases... πŸ€”

toBeDisabled matcher proposal

Describe the feature you'd like:

I would like to have a matcher that would check if the form element is disabled from user's perspective.
In this case, simply checking the 'disabled' attribute is not enough.

Describe alternatives you've considered:

In many cases .toHaveAttribute('disabled') is sufficient alternative.
But I think that the dedicated matcher would be less dependent on the implementation details

Teachability, Documentation, Adoption, Migration Strategy:

Examples and comparison with toHaveAttribute matcher.

// in simple cases toHaveAttribute and toBeDisabled behave the same

// ...
// <button disabled={true}>CLICK</button>
expect(getByText(container, 'CLICK')).toHaveAttribute('disabled')
expect(getByText(container, 'CLICK')).toBeDisabled()
// ...
// toBeDisabled can detect when a disabled state is inherited

// ...
// <fieldset disabled={true}><button>CLICK</button></fieldset>
expect(getByText(container, 'CLICK')).not.toHaveAttribute('disabled')
expect(getByText(container, 'CLICK')).toBeDisabled()
// ...
// 'a' element is not disabled, even if it has the 'disabled' attribute

// ...
// <a href="http://..." disabled={true}>CLICK</a>
expect(getByText(container, 'CLICK')).toHaveAttribute('disabled')
expect(getByText(container, 'CLICK')).not.toBeDisabled()
// ...

toBeEmpty yields false positives with self closing tags

  • jest-dom version: 3.1.2
  • node version: 10.15.0
  • npm (or yarn) version: 6.4.1 and 1.13.0

Relevant code or config

expect(<div />).toBeEmpty(); // Fails

What you did:

Tried asserting that a React component would be empty based on certain props.

What happened:

Test fails with the following message:

expect(received).toBeEmpty()

Expected value to be empty received:
    <div />

Reproduction repository:

Problem description:

Suggested solution:

Not really sure but I’m open to looking into it.

Congrats!

Hey! Congrats on the 1.0.0 release! πŸŽ‰

Accessibility-related matchers

Describe the feature you'd like:

In the light of projects like Reach UI and react-beautiful-dnd and others like them, that have a focus on accessibility, I was thinking that it could be useful to test that stuff in the Dom have some features that help with accessibility.

I'm not sure though, if it'd be enough to test for aria- attributes with toHaveAttribute, or if there's something else we could do with custom matchers that would help even more. It does not help that I my self am fairly new to being aware and worried about a11y in my apps (shame on me!) but I'm catching up, and wanted to raise the issue here in hope for others to chime in and determine if there could be something jest-dom could do about it.

Suggested implementation:

Not sure yet. Not even sure if it's needed and kind of matchers we would need.

Describe alternatives you've considered:

Not sure of any. If you know of any, let me know in the comments.

Teachability, Documentation, Adoption, Migration Strategy:

TODO

Is there a migration guide for old jest-dom ?

Sorry but yet, if i just switch from jest-dom to @testing-library/jest-dom nothing behave as expected.

My guess is that Jest may not manage it yet, but i did not find any migration helper. Is there one ?

Should .toHaveTextContent be case-sensitive?

I don't know if this is a bug or it is a feature, but I expected that .toHaveTextContent was case-sensitive. I could address that if it is a bug.

  • jest-dom version: 2.1.1

What you did:

<div className="App">
  <h1>Hello CodeSandbox</h1>
  <h2>Start editing to see some magic happen!</h2>
</div>

I expect the expect below would fail, but it passes.

expect(subject.container.querySelector("h1")).toHaveTextContent("hello codesandbox");

toHaveTextContent should ignore whitespace

  • jest-dom version: 1.0.0

What you did:

//  <span>
//    Step
//      1
//    of 4
//  </span>

expect(container.querySelector('span')).toHaveTextContent('Step 1 of 4')

What happened:

    expect(element).toHaveTextContent()

    Expected element to have text content:
      Step 1 of 4
    Received:

          Step
            1
          of 4

Problem description:

This was initially reported in testing-library/react-testing-library#53, and it was really about a bug in testing-library/dom-testing-library#19. However, this also applies to a piece of code in jest-dom. The custom matchet .toHaveTextContent should also ignore a node's whitespace in its text content before determining if the text matches the expectation.

Suggested solution:

Normalize the text of a node before using to match it with the expected text. Similar to what was done in testing-library/dom-testing-library#19

New custom matchers proposal

After a quick scan of the custom matchers provided in chai-dom I think there are many in there that I consider to be just for convenience and I do not favor adding them for the moment (for instance "to have id" and "to have value" are just a minor convenience over simply using .toHaveAttribute).

However, there are a few that I think could be good additions to this library. I think the overall criteria for what is considered a good addition is that doing the equivalent assertion on our own makes the test code more verbose and/or harder to read.

Here are some of the ones I see as convenient to add (all up for discussion):

  • expect(element).toBeEmpty(): the element exists but it contains no child elements. Not sure if that name is too generic outside of the scope of dom matchers. Also not sure if it's really just a convenience over a simple alternative with vanilla DOM APIs.
  • expect(element).toBeDisplayed(): asserts that display is not equal to "none".
  • expect(element).toBeVisible(): asserts that visibility is not "hidden" or "collapsed".

Additionally I wonder if instead of the last two, we could get away with a single .toHaveStyle that would work similar to .toHaveAttribute (e.g. .toHaveStyle('display', 'none'), .not.toHaveStyle('visibility', 'hidden'))

support for asymmetricMatch as the value for toHaveAttribute matcher

Describe the feature you'd like:

Adding support for asymmetricMatchers like expec.stringContaining as the value to toHaveAttribute matcher
Eg:

      expect(getByLabelText(/Download Template/)).toHaveAttribute(
        "href",
        expect.stringContaining("?type=instruments")
      );

Suggested implementation:

Describe alternatives you've considered:

As of now this is achived by

      expect(getByLabelText(/Download Template/).getAttribute("href")).toEqual(
        expect.stringContaining("type=instruments")
      );

Teachability, Documentation, Adoption, Migration Strategy:

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.