def assert_support(self, contents, expected_versions=None, expected_supports=None, issues=None): row_cell = '<td>%s</td>' % contents parsed = compat_support_grammar['html'].parse(row_cell) self.visitor = CompatSupportVisitor(self.feature_id, self.browser_id, self.browser_name, self.browser_slug) self.visitor.visit(parsed) expected_versions = expected_versions or [] expected_supports = expected_supports or [] self.assertEqual(len(expected_versions), len(expected_supports)) for version, support in zip(expected_versions, expected_supports): if 'id' not in version: version['id'] = '_{}-{}'.format(self.browser_name, version['version']) version['browser'] = self.browser_id if 'id' not in support: support['id'] = '_{}-{}'.format(self.feature_id, version['id']) support['version'] = version['id'] support['feature'] = self.feature_id self.assertEqual(expected_versions, self.visitor.versions) self.assertEqual(expected_supports, self.visitor.supports) self.assertEqual(issues or [], self.visitor.issues)
def assert_support( self, contents, expected_versions=None, expected_supports=None, issues=None): row_cell = '<td>%s</td>' % contents parsed = compat_support_grammar['html'].parse(row_cell) self.visitor = CompatSupportVisitor( self.feature_id, self.browser_id, self.browser_name, self.browser_slug) self.visitor.visit(parsed) expected_versions = expected_versions or [] expected_supports = expected_supports or [] self.assertEqual(len(expected_versions), len(expected_supports)) for version, support in zip(expected_versions, expected_supports): if 'id' not in version: version['id'] = '_{}-{}'.format( self.browser_name, version['version']) version['browser'] = self.browser_id if 'id' not in support: support['id'] = '_{}-{}'.format(self.feature_id, version['id']) support['version'] = version['id'] support['feature'] = self.feature_id self.assertEqual(expected_versions, self.visitor.versions) self.assertEqual(expected_supports, self.visitor.supports) self.assertEqual(issues or [], self.visitor.issues)
class TestSupportVisitor(TestCase): scope = 'compatibility support' def setUp(self): self.feature_id = '_feature' self.browser_id = '_browser' self.browser_name = 'Browser' self.browser_slug = 'browser' def set_browser(self, browser): self.browser_id = browser.id self.browser_name = browser.name self.browser_slug = browser.slug def assert_support( self, contents, expected_versions=None, expected_supports=None, issues=None): row_cell = '<td>%s</td>' % contents parsed = compat_support_grammar['html'].parse(row_cell) self.visitor = CompatSupportVisitor( self.feature_id, self.browser_id, self.browser_name, self.browser_slug) self.visitor.visit(parsed) expected_versions = expected_versions or [] expected_supports = expected_supports or [] self.assertEqual(len(expected_versions), len(expected_supports)) for version, support in zip(expected_versions, expected_supports): if 'id' not in version: version['id'] = '_{}-{}'.format( self.browser_name, version['version']) version['browser'] = self.browser_id if 'id' not in support: support['id'] = '_{}-{}'.format(self.feature_id, version['id']) support['version'] = version['id'] support['feature'] = self.feature_id self.assertEqual(expected_versions, self.visitor.versions) self.assertEqual(expected_supports, self.visitor.supports) self.assertEqual(issues or [], self.visitor.issues) def test_version(self): self.assert_support('1.0', [{'version': '1.0'}], [{'support': 'yes'}]) def test_version_matches(self): version = self.get_instance('Version', ('firefox_desktop', '1.0')) self.set_browser(version.browser) self.assert_support( '1.0', [{'version': '1.0', 'id': version.id}], [{'support': 'yes'}]) def test_new_version_existing_browser(self): browser = self.get_instance('Browser', 'firefox_desktop') self.set_browser(browser) issue = ( 'unknown_version', 4, 7, {'browser_id': browser.id, 'browser_name': {'en': 'Firefox for Desktop'}, 'browser_slug': 'firefox_desktop', 'version': '2.0'}) self.assert_support( '2.0', [{'version': '2.0'}], [{'support': 'yes'}], issues=[issue]) def test_support_matches(self): version = self.get_instance('Version', ('firefox_desktop', '1.0')) self.set_browser(version.browser) feature = self.get_instance( 'Feature', 'web-css-background-size-contain_and_cover') self.feature_id = feature.id support = self.create(Support, version=version, feature=feature) self.assert_support( '1.0', [{'version': '1.0', 'id': version.id}], [{'support': 'yes', 'id': support.id}]) def test_compatno(self): self.assert_support( '{{CompatNo}}', [{'version': 'current'}], [{'support': 'no'}]) def test_compatversionunknown(self): self.assert_support( '{{CompatVersionUnknown}}', [{'version': 'current'}], [{'support': 'yes'}]) def test_compatunknown(self): self.assert_support('{{CompatUnknown}}', [], []) def test_compatgeckodesktop(self): self.assert_support( '{{CompatGeckoDesktop("1")}}', [{'version': '1.0'}], [{'support': 'yes'}]) def test_compatgeckodesktop_bad_num(self): self.assert_support( '{{CompatGeckoDesktop("1.1")}}', issues=[('compatgeckodesktop_unknown', 4, 33, {'version': '1.1'})]) def test_compatgeckofxos(self): self.assert_support( '{{CompatGeckoFxOS("7")}}', [{'version': '1.0'}], [{'support': 'yes'}]) def test_compatgeckofxos_bad_version(self): self.assert_support( '{{CompatGeckoFxOS("999999")}}', issues=[('compatgeckofxos_unknown', 4, 33, {'version': '999999'})]) def test_compatgeckofxos_bad_override(self): self.assert_support( '{{CompatGeckoFxOS("18","5.0")}}', issues=[('compatgeckofxos_override', 4, 35, {'override': '5.0', 'version': '18'})]) def test_compatgeckomobile(self): self.assert_support( '{{CompatGeckoMobile("1")}}', [{'version': '1.0'}], [{'support': 'yes'}]) def test_compatandroid(self): self.assert_support( '{{CompatAndroid("3.0")}}', [{'version': '3.0'}], [{'support': 'yes'}]) def test_compatnightly(self): self.assert_support( '{{CompatNightly}}', [{'version': 'nightly'}], [{'support': 'yes'}]) def test_unknown_kumascript(self): issues = [( 'unknown_kumascript', 4, 19, {'name': 'UnknownKuma', 'args': [], 'scope': 'compatibility support', 'kumascript': '{{UnknownKuma}}'})] self.assert_support('{{UnknownKuma}}', issues=issues) def test_with_prefix_and_break(self): self.assert_support( ('{{CompatVersionUnknown}}{{property_prefix("-webkit")}}<br>\n' ' 2.3'), [{'version': 'current'}, {'version': '2.3'}], [{'support': 'yes', 'prefix': '-webkit'}, {'support': 'yes'}]) def test_p_tags(self): self.assert_support( '<p>4.0</p><p>32</p>', [{'version': '4.0'}, {'version': '32.0'}], [{'support': 'yes'}, {'support': 'yes'}]) def test_two_line_note(self): self.assert_support( '18<br>\n(behind a pref) [1]', [{'version': '18.0'}], [{'support': 'yes', 'footnote_id': ('1', 27, 30)}], issues=[('inline_text', 10, 27, {'text': '(behind a pref)'})]) def test_removed_in_gecko(self): self.assert_support( ('{{ CompatGeckoMobile("6.0") }}<br>' 'Removed in {{ CompatGeckoMobile("23.0") }}'), [{'version': '6.0'}, {'version': '23.0'}], [{'support': 'yes'}, {'support': 'no'}]) def test_multi_br(self): self.assert_support( ('{{ CompatGeckoMobile("6.0") }}<br><br>' 'Removed in {{ CompatGeckoMobile("23.0") }}'), [{'version': '6.0'}, {'version': '23.0'}], [{'support': 'yes'}, {'support': 'no'}]) def test_removed_in_version(self): self.assert_support( 'Removed in 32', [{'version': '32.0'}], [{'support': 'no'}]) def test_unprefixed(self): # https://developer.mozilla.org/en-US/docs/Web/API/AudioContext.createBufferSource self.assert_support( '32 (unprefixed)', [{'version': '32.0'}], [{'support': 'yes'}]) def test_partial(self): # https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor self.assert_support( '10, partial', [{'version': '10.0'}], [{'support': 'partial'}]) def test_unmatched_free_text(self): self.assert_support( '32 (or earlier)', [{'version': '32.0'}], [{'support': 'yes'}], issues=[('inline_text', 7, 19, {'text': '(or earlier)'})]) def test_code_block(self): # https://developer.mozilla.org/en-US/docs/Web/CSS/order self.assert_support( '32 with alt name <code>foobar</code>', [{'version': '32.0'}], [{'support': 'yes'}], issues=[ ('inline_text', 7, 21, {'text': 'with alt name'}), ('inline_text', 21, 40, {'text': '<code>foobar</code>'})]) def test_spaces(self): self.assert_support(' ') def test_prefix_plus_footnote(self): self.assert_support( '18{{property_prefix("-webkit")}} [1]', [{'version': '18.0'}], [{'support': 'partial', 'prefix': '-webkit', 'footnote_id': ('1', 37, 40)}]) def test_prefix_double_footnote(self): # https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule self.assert_support( '{{ CompatGeckoDesktop("17") }} [1][2]', [{'version': '17.0'}], [{'support': 'yes', 'footnote_id': ('1', 35, 38)}], issues=[('footnote_multiple', 38, 41, {'prev_footnote_id': '1', 'footnote_id': '2'})]) def test_double_footnote_link_sup(self): # https://developer.mozilla.org/en-US/docs/Web/CSS/flex self.assert_support( '{{CompatGeckoDesktop("20.0")}} ' '<sup><a href="#bc2">[2]</a><a href="#bc3">[3]</a></sup>', [{'version': '20.0'}], [{'support': 'yes', 'footnote_id': ('2', 55, 58)}], issues=[('footnote_multiple', 77, 80, {'prev_footnote_id': '2', 'footnote_id': '3'})]) def test_star_footnote(self): # TODO: use raw footnote once footnote section is converted self.assert_support( '{{CompatGeckoDesktop("20.0")}} [***]', [{'version': '20.0'}], [{'support': 'yes', 'footnote_id': ('3', 35, 40)}]) def test_nbsp(self): self.assert_support( '15 {{property_prefix("webkit")}}', [{'version': '15.0'}], [{'support': 'yes', 'prefix': 'webkit'}]) def test_other_kumascript(self): issue = ( 'unexpected_kumascript', 7, 30, {'kumascript': '{{experimental_inline}}', 'name': 'experimental_inline', 'args': [], 'scope': self.scope, 'expected_scopes': 'compatibility feature'}) self.assert_support( '22 {{experimental_inline}}', [{'version': '22.0'}], [{'support': 'yes'}], issues=[issue]) def test_multiversion_prefix_no(self): # https://developer.mozilla.org/en-US/docs/Web/API/Text/replaceWholeText self.assert_support( '{{CompatVersionUnknown}} [1] <br> 30.0 <br> {{CompatNo}} 41.0', [{'version': 'current'}, {'version': '30.0'}, {'version': '41.0'}], [{'support': 'yes', 'footnote_id': ('1', 29, 33)}, {'support': 'yes'}, {'support': 'no'}]) def test_multiversion_suffix_no(self): self.assert_support( '{{CompatVersionUnknown}} [1] <br> 30.0 <br> 41.0 {{CompatNo}}', [{'version': 'current'}, {'version': '30.0'}, {'version': '41.0'}], [{'support': 'yes', 'footnote_id': ('1', 29, 33)}, {'support': 'yes'}, {'support': 'no'}])
class TestSupportVisitor(TestCase): scope = 'compatibility support' def setUp(self): self.feature_id = '_feature' self.browser_id = '_browser' self.browser_name = 'Browser' self.browser_slug = 'browser' def set_browser(self, browser): self.browser_id = browser.id self.browser_name = browser.name self.browser_slug = browser.slug def assert_support(self, contents, expected_versions=None, expected_supports=None, issues=None): row_cell = '<td>%s</td>' % contents parsed = compat_support_grammar['html'].parse(row_cell) self.visitor = CompatSupportVisitor(self.feature_id, self.browser_id, self.browser_name, self.browser_slug) self.visitor.visit(parsed) expected_versions = expected_versions or [] expected_supports = expected_supports or [] self.assertEqual(len(expected_versions), len(expected_supports)) for version, support in zip(expected_versions, expected_supports): if 'id' not in version: version['id'] = '_{}-{}'.format(self.browser_name, version['version']) version['browser'] = self.browser_id if 'id' not in support: support['id'] = '_{}-{}'.format(self.feature_id, version['id']) support['version'] = version['id'] support['feature'] = self.feature_id self.assertEqual(expected_versions, self.visitor.versions) self.assertEqual(expected_supports, self.visitor.supports) self.assertEqual(issues or [], self.visitor.issues) def test_version(self): self.assert_support('1.0', [{'version': '1.0'}], [{'support': 'yes'}]) def test_version_matches(self): version = self.get_instance('Version', ('firefox_desktop', '1.0')) self.set_browser(version.browser) self.assert_support('1.0', [{ 'version': '1.0', 'id': version.id }], [{ 'support': 'yes' }]) def test_new_version_existing_browser(self): browser = self.get_instance('Browser', 'firefox_desktop') self.set_browser(browser) issue = ('unknown_version', 4, 7, { 'browser_id': browser.id, 'browser_name': { 'en': 'Firefox for Desktop' }, 'browser_slug': 'firefox_desktop', 'version': '2.0' }) self.assert_support('2.0', [{ 'version': '2.0' }], [{ 'support': 'yes' }], issues=[issue]) def test_support_matches(self): version = self.get_instance('Version', ('firefox_desktop', '1.0')) self.set_browser(version.browser) feature = self.get_instance( 'Feature', 'web-css-background-size-contain_and_cover') self.feature_id = feature.id support = self.create(Support, version=version, feature=feature) self.assert_support('1.0', [{ 'version': '1.0', 'id': version.id }], [{ 'support': 'yes', 'id': support.id }]) def test_compatno(self): self.assert_support('{{CompatNo}}', [{ 'version': 'current' }], [{ 'support': 'no' }]) def test_compatversionunknown(self): self.assert_support('{{CompatVersionUnknown}}', [{ 'version': 'current' }], [{ 'support': 'yes' }]) def test_compatunknown(self): self.assert_support('{{CompatUnknown}}', [], []) def test_compatgeckodesktop(self): self.assert_support('{{CompatGeckoDesktop("1")}}', [{ 'version': '1.0' }], [{ 'support': 'yes' }]) def test_compatgeckodesktop_bad_num(self): self.assert_support('{{CompatGeckoDesktop("1.1")}}', issues=[('compatgeckodesktop_unknown', 4, 33, { 'version': '1.1' })]) def test_compatgeckofxos(self): self.assert_support('{{CompatGeckoFxOS("7")}}', [{ 'version': '1.0' }], [{ 'support': 'yes' }]) def test_compatgeckofxos_bad_version(self): self.assert_support('{{CompatGeckoFxOS("999999")}}', issues=[('compatgeckofxos_unknown', 4, 33, { 'version': '999999' })]) def test_compatgeckofxos_bad_override(self): self.assert_support('{{CompatGeckoFxOS("18","5.0")}}', issues=[('compatgeckofxos_override', 4, 35, { 'override': '5.0', 'version': '18' })]) def test_compatgeckomobile(self): self.assert_support('{{CompatGeckoMobile("1")}}', [{ 'version': '1.0' }], [{ 'support': 'yes' }]) def test_compatandroid(self): self.assert_support('{{CompatAndroid("3.0")}}', [{ 'version': '3.0' }], [{ 'support': 'yes' }]) def test_compatnightly(self): self.assert_support('{{CompatNightly}}', [{ 'version': 'nightly' }], [{ 'support': 'yes' }]) def test_unknown_kumascript(self): issues = [('unknown_kumascript', 4, 19, { 'name': 'UnknownKuma', 'args': [], 'scope': 'compatibility support', 'kumascript': '{{UnknownKuma}}' })] self.assert_support('{{UnknownKuma}}', issues=issues) def test_with_prefix_and_break(self): self.assert_support( ('{{CompatVersionUnknown}}{{property_prefix("-webkit")}}<br>\n' ' 2.3'), [{ 'version': 'current' }, { 'version': '2.3' }], [{ 'support': 'yes', 'prefix': '-webkit' }, { 'support': 'yes' }]) def test_p_tags(self): self.assert_support('<p>4.0</p><p>32</p>', [{ 'version': '4.0' }, { 'version': '32.0' }], [{ 'support': 'yes' }, { 'support': 'yes' }]) def test_two_line_note(self): self.assert_support('18<br>\n(behind a pref) [1]', [{ 'version': '18.0' }], [{ 'support': 'yes', 'footnote_id': ('1', 27, 30) }], issues=[('inline_text', 10, 27, { 'text': '(behind a pref)' })]) def test_removed_in_gecko(self): self.assert_support(('{{ CompatGeckoMobile("6.0") }}<br>' 'Removed in {{ CompatGeckoMobile("23.0") }}'), [{ 'version': '6.0' }, { 'version': '23.0' }], [{ 'support': 'yes' }, { 'support': 'no' }]) def test_multi_br(self): self.assert_support(('{{ CompatGeckoMobile("6.0") }}<br><br>' 'Removed in {{ CompatGeckoMobile("23.0") }}'), [{ 'version': '6.0' }, { 'version': '23.0' }], [{ 'support': 'yes' }, { 'support': 'no' }]) def test_removed_in_version(self): self.assert_support('Removed in 32', [{ 'version': '32.0' }], [{ 'support': 'no' }]) def test_unprefixed(self): # https://developer.mozilla.org/en-US/docs/Web/API/AudioContext.createBufferSource self.assert_support('32 (unprefixed)', [{ 'version': '32.0' }], [{ 'support': 'yes' }]) def test_partial(self): # https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor self.assert_support('10, partial', [{ 'version': '10.0' }], [{ 'support': 'partial' }]) def test_unmatched_free_text(self): self.assert_support('32 (or earlier)', [{ 'version': '32.0' }], [{ 'support': 'yes' }], issues=[('inline_text', 7, 19, { 'text': '(or earlier)' })]) def test_code_block(self): # https://developer.mozilla.org/en-US/docs/Web/CSS/order self.assert_support('32 with alt name <code>foobar</code>', [{ 'version': '32.0' }], [{ 'support': 'yes' }], issues=[('inline_text', 7, 21, { 'text': 'with alt name' }), ('inline_text', 21, 40, { 'text': '<code>foobar</code>' })]) def test_spaces(self): self.assert_support(' ') def test_prefix_plus_footnote(self): self.assert_support('18{{property_prefix("-webkit")}} [1]', [{ 'version': '18.0' }], [{ 'support': 'partial', 'prefix': '-webkit', 'footnote_id': ('1', 37, 40) }]) def test_prefix_double_footnote(self): # https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule self.assert_support('{{ CompatGeckoDesktop("17") }} [1][2]', [{ 'version': '17.0' }], [{ 'support': 'yes', 'footnote_id': ('1', 35, 38) }], issues=[('footnote_multiple', 38, 41, { 'prev_footnote_id': '1', 'footnote_id': '2' })]) def test_double_footnote_link_sup(self): # https://developer.mozilla.org/en-US/docs/Web/CSS/flex self.assert_support( '{{CompatGeckoDesktop("20.0")}} ' '<sup><a href="#bc2">[2]</a><a href="#bc3">[3]</a></sup>', [{ 'version': '20.0' }], [{ 'support': 'yes', 'footnote_id': ('2', 55, 58) }], issues=[('footnote_multiple', 77, 80, { 'prev_footnote_id': '2', 'footnote_id': '3' })]) def test_star_footnote(self): # TODO: use raw footnote once footnote section is converted self.assert_support('{{CompatGeckoDesktop("20.0")}} [***]', [{ 'version': '20.0' }], [{ 'support': 'yes', 'footnote_id': ('3', 35, 40) }]) def test_nbsp(self): self.assert_support('15 {{property_prefix("webkit")}}', [{ 'version': '15.0' }], [{ 'support': 'yes', 'prefix': 'webkit' }]) def test_other_kumascript(self): issue = ('unexpected_kumascript', 7, 30, { 'kumascript': '{{experimental_inline}}', 'name': 'experimental_inline', 'args': [], 'scope': self.scope, 'expected_scopes': 'compatibility feature' }) self.assert_support('22 {{experimental_inline}}', [{ 'version': '22.0' }], [{ 'support': 'yes' }], issues=[issue]) def test_multiversion_prefix_no(self): # https://developer.mozilla.org/en-US/docs/Web/API/Text/replaceWholeText self.assert_support( '{{CompatVersionUnknown}} [1] <br> 30.0 <br> {{CompatNo}} 41.0', [{ 'version': 'current' }, { 'version': '30.0' }, { 'version': '41.0' }], [{ 'support': 'yes', 'footnote_id': ('1', 29, 33) }, { 'support': 'yes' }, { 'support': 'no' }]) def test_multiversion_suffix_no(self): self.assert_support( '{{CompatVersionUnknown}} [1] <br> 30.0 <br> 41.0 {{CompatNo}}', [{ 'version': 'current' }, { 'version': '30.0' }, { 'version': '41.0' }], [{ 'support': 'yes', 'footnote_id': ('1', 29, 33) }, { 'support': 'yes' }, { 'support': 'no' }])