{"action":"created","issue":{"url":"https://api.github.com/repos/stylelint/stylelint/issues/32","labels_url":"https://api.github.com/repos/stylelint/stylelint/issues/32/labels{/name}","comments_url":"https://api.github.com/repos/stylelint/stylelint/issues/32/comments","events_url":"https://api.github.com/repos/stylelint/stylelint/issues/32/events","html_url":"https://github.com/stylelint/stylelint/issues/32","id":74743669,"number":32,"title":"Testing utilities and conventions","user":{"login":"davidtheclark","id":628431,"avatar_url":"https://avatars.githubusercontent.com/u/628431?v=3","gravatar_id":"","url":"https://api.github.com/users/davidtheclark","html_url":"https://github.com/davidtheclark","followers_url":"https://api.github.com/users/davidtheclark/followers","following_url":"https://api.github.com/users/davidtheclark/following{/other_user}","gists_url":"https://api.github.com/users/davidtheclark/gists{/gist_id}","starred_url":"https://api.github.com/users/davidtheclark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidtheclark/subscriptions","organizations_url":"https://api.github.com/users/davidtheclark/orgs","repos_url":"https://api.github.com/users/davidtheclark/repos","events_url":"https://api.github.com/users/davidtheclark/events{/privacy}","received_events_url":"https://api.github.com/users/davidtheclark/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":10,"created_at":"2015-05-09T19:40:30Z","updated_at":"2015-05-10T13:31:12Z","closed_at":"2015-05-10T13:31:12Z","body":"The vast majority of tests that we write for rules will be doing the exact same thing: check whether a given CSS string passes or causes a warning with an expected message.\r\n\r\nSo I'm thinking we should have some functions that make it very, very easy to run these standard tests and log meaningful messages. (Of course, if somebody has something different to do they can always *not* use these standard functions.)\r\n\r\nThis morning I worked out a possible approach, and I wanted to run it by you all before I went too far with it.\r\n\r\nThe following creates a ruleTester that exposes `ok()` and `notOk()` functions that check for no warnings or warnings (with correct messages) and logs in a meaningful way:\r\n\r\n```js\r\nimport postcss from \"postcss\"\r\nimport jsesc from \"jsesc\"\r\n\r\nexport default function ruleTester(rule) {\r\n  return {\r\n    ok: function (t, cssString, options) {\r\n      postcssProcess(cssString, options, result => {\r\n        t.comment(jsesc(cssString))\r\n        t.equal(result.warnings().length, 0, `no warnings`)\r\n      })\r\n    },\r\n    notOk: function (t, cssString, options, message) {\r\n      postcssProcess(cssString, options, result => {\r\n        const warnings = result.warnings()\r\n        t.comment(jsesc(cssString))\r\n        t.equal(warnings.length, 1, `one warning`)\r\n        t.equal(warnings[0].text, message, `correct warning message`)\r\n      })\r\n    },\r\n  }\r\n\r\n  function postcssProcess(cssString, options, callback) {\r\n    postcss()\r\n      .use(rule(options))\r\n      .process(cssString)\r\n      .then(callback)\r\n  }\r\n}\r\n```\r\n\r\nI'd use it like this (the third test deliberately fails):\r\n\r\n```js\r\nimport test from \"tape\"\r\nimport { ruleTester, ruleTestTitle } from \"../../../testUtils\"\r\nimport blockOpeningBraceBefore, { ruleName, messages } from \"..\"\r\n\r\nconst testRule = ruleTester(blockOpeningBraceBefore)\r\n\r\ntest(ruleTestTitle(ruleName, \"'space'\"), t => {\r\n  testRule.ok(t, \"body { color: pink; }\", \"space\")\r\n  testRule.ok(t, \"@media print { color: pink; }\", \"space\")\r\n  testRule.notOk(t, \"body\\n{ color: pink; }\", \"newline\", messages.expected(\"newline\"))\r\n  testRule.notOk(t, \"@media print\\n{ color: pink; }\", \"space\", messages.expected(\"space\"))\r\n  t.end()\r\n})\r\n```\r\n\r\nAnd that outputs TAP output like this:\r\n\r\n```\r\nTAP version 13\r\n# block-opening-brace-before: 'space'\r\n# body { color: pink; }\r\nok 1 no warnings\r\n# @media print { color: pink; }\r\nok 2 no warnings\r\n# body\\n{ color: pink; }\r\nnot ok 3 one warning\r\n  ---\r\n    operator: equal\r\n    expected: 1\r\n    actual:   0\r\n  ...\r\n# @media print\\n{ color: pink; }\r\nok 4 one warning\r\nok 5 correct warning message\r\n\r\n1..5\r\n# tests 5\r\n# pass  4\r\n# fail  1\r\n```\r\n\r\nOr tap-spec output like this:\r\n\r\n```\r\n  block-opening-brace-before: 'space'\r\n\r\n\r\n  body { color: pink; }\r\n\r\n    ✓ no warnings\r\n\r\n  @media print { color: pink; }\r\n\r\n    ✓ no warnings\r\n\r\n  body\\n{ color: pink; }\r\n\r\n    ✗ one warning\r\n\r\n  @media print\\n{ color: pink; }\r\n\r\n    ✓ one warning\r\n    ✓ correct warning message\r\n```\r\n\r\nOr faucet output like this:\r\n\r\n```\r\n✓ block-opening-brace-before: 'space'\r\n✓ body { color: pink; }\r\n✓ @media print { color: pink; }\r\n⨯ body\\n{ color: pink; }\r\n  not ok 3 one warning\r\n    ---\r\n      operator: equal\r\n      expected: 1\r\n      actual:   0\r\n    ...\r\n✓ @media print\\n{ color: pink; }\r\n# tests 5\r\n# pass  4\r\n⨯ fail  1\r\n```\r\n\r\n**What do you think?** Is that a useful abstraction for us? Are the error messages as clear as we can make them? Any suggestions for improvement?\r\n\r\nI think it will be very handy as we write thousands of little tests to have functions that do something like this, at least ..."},"comment":{"url":"https://api.github.com/repos/stylelint/stylelint/issues/comments/100642509","html_url":"https://github.com/stylelint/stylelint/issues/32#issuecomment-100642509","issue_url":"https://api.github.com/repos/stylelint/stylelint/issues/32","id":100642509,"user":{"login":"MoOx","id":157534,"avatar_url":"https://avatars.githubusercontent.com/u/157534?v=3","gravatar_id":"","url":"https://api.github.com/users/MoOx","html_url":"https://github.com/MoOx","followers_url":"https://api.github.com/users/MoOx/followers","following_url":"https://api.github.com/users/MoOx/following{/other_user}","gists_url":"https://api.github.com/users/MoOx/gists{/gist_id}","starred_url":"https://api.github.com/users/MoOx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MoOx/subscriptions","organizations_url":"https://api.github.com/users/MoOx/orgs","repos_url":"https://api.github.com/users/MoOx/repos","events_url":"https://api.github.com/users/MoOx/events{/privacy}","received_events_url":"https://api.github.com/users/MoOx/received_events","type":"User","site_admin":false},"created_at":"2015-05-10T13:31:12Z","updated_at":"2015-05-10T13:31:12Z","body":"Closed in favor of #33"}}