def test_set_custom_breakpoint_key_Valid(self): valid_css_classes = ( 'padding-25-820-up', 'display-480-down', 'margin-5-2-5-2-1000-up', 'display-960-up-i', 'display-3_2rem-down' ) names = ['padding', 'display', 'margin', 'display', 'display', ] values = ['25', 'none', '5-2-5-2', 'none', 'none', ] priorities = ['', '', '', 'important', '', ] limit_key = ('-up', '-down', '-up', '-up', '-down', ) breakpoint = ('-820', '-480', '-1000', '-960', '-3_2rem', ) converted_breakpoint = (px_to_em('820'), px_to_em('480'), px_to_em('1000'), px_to_em('960'), '3.2rem', ) for i, css_class in enumerate(valid_css_classes): css_property = Property(name=names[i], value=values[i], priority=priorities[i]) breakpoint_parser = BreakpointParser(css_class=css_class, css_property=css_property) self.assertTrue(breakpoint_parser.is_breakpoint, msg=breakpoint_parser.css_class) self.assertEqual( breakpoint_parser.breakpoint_dict['custom'][limit_key[i]], converted_breakpoint[i], msg=converted_breakpoint[i] + ' dict: ' + breakpoint_parser.breakpoint_dict['custom'][limit_key[i]] ) self.assertEqual( breakpoint_parser.breakpoint_dict['custom']['breakpoint'], breakpoint[i], msg=breakpoint[i] + ' dict: ' + breakpoint_parser.breakpoint_dict['custom']['breakpoint'] )
def test_build_media_query_invalid_limit_key(self): css_class = 'padding-100-small-up' name = 'padding' value = px_to_em('100') expected = '' css_property = Property(name=name, value=value, priority='') breakpoint_parser = BreakpointParser(css_class=css_class, css_property=css_property) breakpoint_parser.limit_key = 'invalid_key' css = breakpoint_parser.build_media_query() self.assertEqual(css, expected)
def test_css_for_up_wrong_limit_key(self): css_class = 'padding-100-small-up' name = 'padding' value = px_to_em('100') expected = '' css_property = Property(name=name, value=value, priority='') breakpoint_parser = BreakpointParser(css_class=css_class, css_property=css_property) breakpoint_parser.limit_key = '-only' # Change to WRONG LIMIT KEY css = breakpoint_parser.css_for_up() self.assertEqual(css, expected)
def test_build_media_query_up_general_usage(self): css_class = 'padding-100-small-up' name = 'padding' value = px_to_em('100') expected = ( '@media only screen and (min-width: 15.0625em) {\n' + '\t.padding-100-small-up {\n' + '\t\tpadding: 6.25em;\n' + '\t}\n' + '}\n\n' ) css_property = Property(name=name, value=value, priority='') breakpoint_parser = BreakpointParser(css_class=css_class, css_property=css_property) css = breakpoint_parser.build_media_query() self.assertEqual(css, expected)
def test_css_for_down_general_usage(self): css_class = 'padding-100-medium-down' name = 'padding' value = px_to_em('100') expected = ( '@media only screen and (max-width: 45.0em) {\n' + '\t.padding-100-medium-down {\n' + '\t\tpadding: 6.25em;\n' + '\t}\n' + '}\n\n' ) css_property = Property(name=name, value=value, priority='') breakpoint_parser = BreakpointParser(css_class=css_class, css_property=css_property) css = breakpoint_parser.css_for_down() self.assertEqual(css, expected)
def test_css_for_only_general_usage_important(self): css_class = 'padding-100-large-only-i' name = 'padding' value = px_to_em('100') priority = 'important' expected = ( '@media only screen and (min-width: 45.0625em) and (max-width: 64.0em) {\n' + '\t.padding-100-large-only-i {\n' + '\t\tpadding: 6.25em !important;\n' + '\t}\n' + '}\n\n' ) css_property = Property(name=name, value=value, priority=priority) breakpoint_parser = BreakpointParser(css_class=css_class, css_property=css_property) css = breakpoint_parser.css_for_only() self.assertEqual(css, expected)
def test_write_blowdrycss_settings_dot_py(self): settings_file = 'blowdrycss_settings.py' # Remove it if it exists. if path.isfile(settings_file): remove(settings_file) # Identical section of code from blowdrycss.py for test purposes. write_blowdrycss_settings_dot_py() # Import from the current folder. try: import blowdrycss_settings as settings # development case except ImportError: import blowdrycss.unit_tests.blowdrycss_settings as settings # python setup.py test # test file existence self.assertTrue(path.isfile('blowdrycss_settings.py')) # test directory and file_type settings cwd = getcwd() self.assertTrue( settings.markdown_directory == path.join(cwd, 'docs', 'markdown'), msg=settings.markdown_directory + '\t' + path.join(cwd, 'docs', 'markdown') ) self.assertTrue(settings.project_directory == cwd) self.assertTrue(settings.css_directory == path.join(cwd, 'css')) self.assertTrue(settings.docs_directory == path.join(cwd, 'docs')) self.assertTrue(settings.file_types == ('*.html', )) # test accessibility of true settings true_settings = [ settings.timing_enabled, settings.human_readable, settings.minify, settings.media_queries_enabled, settings.use_em ] for true_setting in true_settings: self.assertTrue(true_setting) # test accessibility of false settings false_settings = [settings.markdown_docs, settings.html_docs, settings.rst_docs] for false_setting in false_settings: self.assertFalse(false_setting) # test base, px_to_em, and breakpoints self.assertTrue(settings.base == 16) self.assertTrue(settings.xxsmall == (settings.px_to_em(0), settings.px_to_em(120))) self.assertTrue(settings.xsmall == (settings.px_to_em(121), settings.px_to_em(240))) self.assertTrue(settings.small == (settings.px_to_em(241), settings.px_to_em(480))) self.assertTrue(settings.medium == (settings.px_to_em(481), settings.px_to_em(720))) self.assertTrue(settings.large == (settings.px_to_em(721), settings.px_to_em(1024))) self.assertTrue(settings.xlarge == (settings.px_to_em(1025), settings.px_to_em(1366))) self.assertTrue(settings.xxlarge == (settings.px_to_em(1367), settings.px_to_em(1920))) self.assertTrue(settings.giant == (settings.px_to_em(1921), settings.px_to_em(2560))) self.assertTrue(settings.xgiant == (settings.px_to_em(2561), settings.px_to_em(2800))) self.assertTrue(settings.xxgiant == (settings.px_to_em(2801), settings.px_to_em(10**6))) # Clean up by deleting test settings file. Can be commented to see what the generated file looks like. # Remove it if it exists. if path.isfile(settings_file): remove(settings_file)
def add_units(self, property_value=''): """ If the property_name requires units, then apply the default units defined in default_property_units_dict. **Rules:** - If use_em is False apply the default units for the property name by looking it up in default_property_units_dict. - Unit that have default units of ``px`` are converted to ``em`` if use_em is True. - If ``property_value`` has multiple property values, then split it apart. - If the value already has units, then pass it through unchanged. - The value provided shall possess negative signs and decimal points. - Mixed units are allowed, but **not recommended**. - Values shall only contain [] e.g. -1.25 can be processed, but n1_25 cannot be processed. :type property_value: str :param property_value: A string containing one or more space delimited alphanumeric characters. :return: (str) -- Returns the property value with the default or converted units added. >>> # Convert 'px' to 'em' >>> unit_parser = UnitParser(property_name='padding', use_em=True) >>> unit_parser.add_units('1 2 1 2') 0.0625em 0.125em 0.0625em 0.125em >>> # Use default units >>> unit_parser.use_em = False >>> unit_parser.add_units('1 2 1 2') 1px 2px 1px 2px >>> # Values already have units or are not parsable pass through >>> # True produces the same output. >>> unit_parser.use_em = False >>> unit_parser.add_units('55zp') 55zp >>> unit_parser.add_units('17rem') 17rem >>> # Unitless ``property_name`` >>> # causes ``property_value`` to pass through. >>> unit_parser.property_name = 'font-weight' >>> unit_parser.add_units('200') 200 >>> # Mixed units cases - Not a Recommended Practice, >>> # but represent valid CSS. Be careful. >>> unit_parser.use_em = False >>> unit_parser.add_units('5em 6 5em 6') 5em 6px 5em 6px >>> unit_parser.use_em = True >>> unit_parser.add_units('1em 100 4cm 9rem') 1em 6.25em 4cm 9rem """ new_value = [] try: default_units = self.default_property_units_dict[self.property_name] # See if property_name has units. for val in property_value.split(): # single, double and quadruple if set(val) <= self.allowed: val = val.replace('px', '') # Handle 'px' units case. if settings.use_em and default_units == 'px': # Convert units if required. new_value.append(settings.px_to_em(pixels=val)) else: new_value.append(val + default_units) # Use default units. else: new_value.append(val) # Pass through and ignore value. property_value = ' '.join(new_value) # Put the new values back together. except KeyError: pass # Property is unitless. return property_value
def set_custom_breakpoint_key(self): """ Assuming that a limit key is found, but a standard breakpoint key is not found in the ``css_class``; determine if a properly formatted custom breakpoint is defined. **Custom Breakpoint Rules:** - Must begin with an integer. - May contain underscores ``_`` to represent decimal points. - May end with any allowed unit (em|ex|px|in|cm|mm|pt|pc|q|ch|rem|vw|vh|vmin|vmax). - Must not be negative. - Unit conversion is based on the related setting in blowdrycss_settings.py. **Pattern Explained** - ``pattern = r'[a-zA-Z].*\-([0-9]*_?[0-9]*?(em|ex|px|in|cm|mm|pt|pc|q|ch|rem|vw|vh|vmin|vmax)?)\-(up|down)\-?'`` - ``[a-zA-Z]`` -- css_class must begin with a letter. - ``.*`` -- First letter may be followed by any number of characters. - ``\-`` -- A dash will appear before the substring pattern. - ``([0-9]*_?[0-9]*?(em|ex|px|in|cm|mm|pt|pc|q|ch|rem|vw|vh|vmin|vmax)?)`` -- Substring pattern begins with A number that could contain an ``_`` to encode an optional decimal point followed by more numbers. Followed by an optional unit of measure. - ``\-(up|down)`` -- Substring pattern must end with either ``-up`` or ``-down``. - ``\-?`` -- Substring pattern may or may not be followed by a dash since it could be the end of a string or :return: None **Examples:** padding-25-820-up, display-480-down, margin-5-2-5-2-1000-up, display-960-up-i, display-3_2rem-down >>> from cssutils.css import Property >>> # value='inherit' since we do not know if the class is valid yet. >>> name = 'display' >>> value = 'inherit' >>> priority = '' >>> inherit_property = Property(name=name, value=value, priority=priority) >>> breakpoint_parser = BreakpointParser( css_class='padding-25-820-up', css_property=inherit_property ) >>> # BreakpointParser() sets limit_key. >>> print(breakpoint_parser.is_breakpoint) True >>> print(breakpoint_parser.limit_key) '-up' >>> print(breakpoint_parser.breakpoint_dict[breakpoint_parser.breakpoint_key][breakpoint_parser.limit_key]) '51.25em' """ pattern = r'[a-zA-Z].*\-([0-9]*_?[0-9]*?(em|ex|px|in|cm|mm|pt|pc|q|ch|rem|vw|vh|vmin|vmax)?)\-(up|down)\-?' matches = re.findall(pattern, self.css_class) try: encoded_breakpoint = matches[0][0] self.breakpoint_key = 'custom' self.is_breakpoint = True # Add the encoded breakpoint to breakpoint_dict with a prepended dash. self.breakpoint_dict['custom']['breakpoint'] = '-' + encoded_breakpoint # Handle underscore to decimal conversion. (negative values are not permitted) custom_breakpoint = encoded_breakpoint.replace('_', '.') # Handle unit conversion. if use_em: custom_breakpoint = px_to_em(custom_breakpoint) # Add transformed value to breakpoint_dict self.breakpoint_dict['custom'][self.limit_key] = custom_breakpoint except IndexError: # Pattern not found in css_class self.is_breakpoint = False except KeyError: # Impossible to get here unless the regex pattern fails. self.is_breakpoint = False # Dictionary key problems (excludes '-only' case).