@import "true";

@import '../../scss/util/unit';
@import '../../scss/util/value';
@import '../../scss/util/breakpoint';

@include test-module('Breakpoint') {

  // --- Breakpoint: Named ---

  @include test('Breakpoint (Named Default/Up Range) [function]') {
    $test: breakpoint(medium);
    $expect: '(min-width: 40em)';

    @include assert-equal($test, $expect,
      'Converts a named breakpoint to an em value');
  }

  @include test('Breakpoint (Named Only Range) [function]') {
    $test: breakpoint(medium only);
    $expect: '(min-width: 40em) and (max-width: 63.99875em)';

    $test-lowest: breakpoint(small only);
    $expect-lowest: '(max-width: 39.99875em)';

    $test-highest: breakpoint(xxlarge only);
    $expect-highest: '(min-width: 90em)';

    @include assert-equal($test, $expect,
      'Creates a min/max-width range out of a named breakpoint');

    @include assert-equal($test-lowest, $expect-lowest,
      'Creates a max-width range if the breakpoint is the lowest');

    @include assert-equal($test-highest, $expect-highest,
      'Creates a min-width range if the breakpoint is the highest');
  }

  @include test('Breakpoint (Named Down Range) [function]') {
    $test: breakpoint(medium down);
    $expect: '(max-width: 63.99875em)';

    @include assert-equal($test, $expect,
      'Creates a down range out of a medium breakpoint');

    $test-lowest: breakpoint(small down);
    $expect-lowest: '(max-width: 39.99875em)';

    @include assert-equal($test-lowest, $expect-lowest,
      'Creates a down range out of a small breakpoint');

    $test-highest: breakpoint(xxlarge down);
    $expect-highest: '';

    @include assert-equal($test-highest, $expect-highest,
      'Skips media query creation for xxlarge down');
  }


  // --- Breakpoint: HiDPI/Retina ---

  //
  // Note for the following "magic numbers":
  //
  // We expect maximum values to have 1 dot less (dot it is the most precise web unit we have there).
  // But sinces values are not in pixels, we have to calculate what 1px is in these units.
  // See https://www.w3.org/TR/css-values-3/#absolute-lengths
  //
  // For a x2 resolution (device pixels per web pixels - or Dots Per PiXel)
  // 2dppx - 1 dot
  // = 2 - (1 / 96)
  // = 1.98958(...)dppx
  //
  // For a x3 resolution
  // 3dppx - 1 dot
  // = 3 - (1 / 96)
  // = 2.98958(...)dppx
  //
  // etc...
  //

  @include test('Breakpoint (Retina) [function]') {
    $expect-2: '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)';

    @include assert-equal(breakpoint(retina), $expect-2,
      'Creates a x2 HiDPI range out of the retina alias breakpoint');
  }

  @include test('Breakpoint (HIDPI Default/Up Range) [function]') {
    $expect-1-5: '(-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi)';
    $expect-2: '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)';

    @include assert-equal(breakpoint(hidpi-1-5 up), $expect-1-5,
      'Creates a x1.5 HiDPI up range out of a x1.5 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-1-5), $expect-1-5,
      'Creates a x1.5 HiDPI up range out of a x1.5 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-2 up), $expect-2,
      'Creates a x2 HiDPI up range out of a x2 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-2), $expect-2,
      'Creates a x2 HiDPI up range out of a x2 HiDPI breakpoint');
  }

  @include test('Breakpoint (HIDPI Only Range) [function]') {
    $expect-1-5: '(-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.9895833333), (min-resolution: 144dpi) and (max-resolution: 191dpi)';
    $expect-2: '(-webkit-min-device-pixel-ratio: 2) and (-webkit-max-device-pixel-ratio: 2.9895833333), (min-resolution: 192dpi) and (max-resolution: 287dpi)';
    $expect-highest: '(-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi)';

    @include assert-equal(breakpoint(hidpi-1-5 only), $expect-1-5,
      'Creates a x1.5 HiDPI only range out of a x1.5 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-2 only), $expect-2,
      'Creates a x2 HiDPI only range out of a x2 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-3 only), $expect-highest,
      'Creates an up range if the HiDPI breakpoint is the highest');
  }

  @include test('Breakpoint (HIDPI Down Range) [function]') {
    $expect-1-5: '(-webkit-max-device-pixel-ratio: 1.9895833333), (max-resolution: 191dpi)';
    $expect-2: '(-webkit-max-device-pixel-ratio: 2.9895833333), (max-resolution: 287dpi)';
    $expect-highest: '';

    @include assert-equal(breakpoint(hidpi-1-5 down), $expect-1-5,
      'Creates a x1.5 HiDPI down range out of a x1.5 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-2 down), $expect-2,
      'Creates a x2 HiDPI down range out of a x2 HiDPI breakpoint');

    @include assert-equal(breakpoint(hidpi-3 down), $expect-highest,
      'Skips media query creation for highest HiDPI breakpoint down');
  }


  // --- Breakpoint: Value ---

  @include test('Breakpoint (Value Default/Up Range) [function]') {
    $expect: '(min-width: 1em)';

    @include assert-equal(breakpoint(16px), $expect,
      'Converts a pixel breakpoint to em');
    @include assert-equal(breakpoint(1rem), $expect,
      'Converts a rem breakpoint to em');
  }

  @include test('Breakpoint (Value Down Range) [function]') {
    $expect: '(max-width: 1em)';

    @include assert-equal(breakpoint(16px down), $expect,
      'Creates a down range out of a pixel value');
    @include assert-equal(breakpoint(1rem down), $expect,
      'Creates a down range out of a rem value');
    @include assert-equal(breakpoint(1em down), $expect,
      'Creates a down range out of an em value');
  }


  // --- Breakpoint: Orientation ---

  @include test('Breakpoint (Orientation) [function]') {
    @include assert-equal(breakpoint(landscape), '(orientation: landscape)',
      'Creates special media query for landscape');
    @include assert-equal(breakpoint(portrait), '(orientation: portrait)',
      'Creates special media query for portrait');
  }


  // --- Breakpoint: Miscellaneous ---

  @include test('Breakpoint (Empty String) [function]') {
    $expect: '';

    @include assert-equal(breakpoint(small up), $expect,
      'Returns an empty string for the value small up');
    @include assert-equal(breakpoint(0 down), $expect,
      'Returns an empty string for the value 0 down');
    @include assert-equal(breakpoint(0 up), $expect,
      'Returns an empty string for the value 0 up');
  }

  @include test('Breakpoint (Unknown Value) [function]') {
    @include assert-equal(breakpoint(xxxxlarge), '', 'Returns an empty string for non-existant media queries');
  }


  // --- Utilities ---

  @include test('Map Serialize [function]') {
    $input: (
      small: 1em,
      medium: 2em,
      large: 3em,
    );
    $test: -zf-bp-serialize($input);
    $expect: 'small=1em&medium=2em&large=3em';

    @include assert-equal($test, $expect,
      'Converts a Sass map into a string');
  }

  @include test('Map Next [function]') {
    $input: (
      one: 'One',
      two: 'Two',
      three: 'Three',
    );
    $test_next: -zf-map-next($input, two);
    $expect_next: map-get($input, three);

    @include assert-equal($test_next, $expect_next,
      'Returns the next value in a map');

    $test_last: -zf-map-next($input, three);
    $expect_last: null;

    @include assert-equal($test_last, $expect_last,
      'Returns null if the key is last in the map');

    $test_null: -zf-map-next($input, four);
    $expect_null: null;

    @include assert-equal($test_null, $expect_null,
      'Returns null if the key is not in the map');
  }

  @include test('Get Breakpoint Value [function]') {
    $config: (
      small: 0,
      large: 1,
    );
    $test_kittens: -zf-get-bp-val($config, kittens);
    $expect_kittens: null;

    @include assert-equal($test_kittens, $expect_kittens,
      'Given a non-existant breakpoint name, return null');

    $test_match: -zf-get-bp-val($config, large);
    $expect_match: 1;

    @include assert-equal($test_match, $expect_match,
      'Given a matching breakpoint, returns the exact value');
    @include assert-equal(-zf-get-bp-val($config, medium), 0,
      'Given a nearby breakpoint, returns the next lowest value');
    @include assert-equal(-zf-get-bp-val($config, xlarge), 1,
      'Given a nearby breakpoint, returns the next lowest value');
  }
}
