<commit_before>import assert from 'assert';
import os from 'os';
import { transform } from 'babel-core';
import plugin from '../src/';
import { clearCache } from '../src/compressClassName';

describe('babel-plugin-css-in-js', () => {
  function makeOptions(options = {}) {
    return Object.assign({
      plugins: [
        [plugin, Object.assign({ bundleFile: 'tmp/bundle.css' }, options)]
      ],
      filename: 'test'
    }, options.babel);
  }

  function squish(str) {
    return str.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/g, ' ');
  }

  function testTransformed(spec) {
    const options = makeOptions(spec.options);
    const result  = transform(spec.from, options);
    const actual  = squish(result.code);
    let expected  = squish(spec.to);

    if (options.filename) {
      expected = '"use strict"; ' + expected;
    }

    assert.equal(actual, expected);

    return result.metadata.css;
  }

  function testStyleRule(css, className, rule) {
    assert(css);

    const hasClassNameWithRule = new RegExp(`\\.${className}\\s*\\{[^\\}]*?${rule}`);

    assert(hasClassNameWithRule.test(css));
  }

  it('does nothing if no "cssInJS" call is present', () => {
    let code = 'var styles = foo({ foo: { margin: 0 } });';

    const css = testTransformed({ from: code, to: code });

    assert.strictEqual(css, '');
  });

  it('throws if return value of "cssInJS" call is not assigned to a variable', () => {
    assert.throws(() => {
      testTransformed({
        from: `
          cssInJS({ foo: { margin: 0 } });
        `
      });
    }, /must be assigned to a variable/);
  });

  it('returns empty css if empty stylesheet provided', () => {
    const css = testTransformed({
      from: 'var styles = cssInJS({});',
      to:   'var styles = {};'
    });

    assert.strictEqual(css, '');
  });

  it('works without a babel filename option', () => {
    const css = testTransformed({
      from: 'var styles = cssInJS({ foo: { marginTop: -10, content: "foo" } });',
      to:   'var styles = { foo: "unknown-styles-foo" };',
      options: { babel: { filename: undefined } }
    });

    assert(css.indexOf('.unknown-styles-foo') > -1);
  });

  describe('with compressClassNames option set to true', () => {
    beforeEach(() => {
      clearCache({});
      clearCache({ cacheDir: os.tmpdir() });
    });

    it('compresses class names with memory cache', () => {
      const css = testTransformed({
        from: `
          var styles1 = cssInJS({ foo: { margin: 0 }, bar: { padding: 0 } });
          var styles2 = cssInJS({ xyz: { padding: 10 } });
        `,
        to: `
          var styles1 = { foo: "_0", bar: "_1" };
          var styles2 = { xyz: "_2" };
        `,
        options: {
          compressClassNames: true,
          cacheDir: null
        }
      });

      testStyleRule(css, '_0', 'margin: 0');
      testStyleRule(css, '_1', 'padding: 0');
      testStyleRule(css, '_2', 'padding: 10');
    });

    it('compresses class names with disk cache', () => {
      const css = testTransformed({
        from: `
          var styles1 = cssInJS({ foo: { margin: 0 }, bar: { padding: 0 } });
          var styles2 = cssInJS({ xyz: { padding: 10 } });
        `,
        to: `
          var styles1 = { foo: "_0", bar: "_1" };
          var styles2 = { xyz: "_2" };
        `,
        options: {
          compressClassNames: true,
          cacheDir: os.tmpdir()
        }
      });

      testStyleRule(css, '_0', 'margin: 0');
      testStyleRule(css, '_1', 'padding: 0');
      testStyleRule(css, '_2', 'padding: 10');
    });

    it('memoizes compressed class names between runs', () => {
      const css1 = testTransformed({
        from: `var styles = cssInJS({ foo: { margin: 0 } });`,
        to:   `var styles = { foo: "_0" };`,
        options: {
          compressClassNames: true,
          cacheDir: null,
          babel: { filename: 'foo.js' }
        }
      });

      testStyleRule(css1, '_0', 'margin: 0');

      const css2 = testTransformed({
        from: `var styles = cssInJS({ foo: { margin: 0 } });`,
        to:   `var styles = { foo: "_0" };`,
        options: {
          compressClassNames: true,
          cacheDir: null,
          babel: { filename: 'foo.js' }
        }
      });

      testStyleRule(css2, '_0', 'margin: 0');
    });
  });

  describe('with vendorPrefixes option set to true', () => {
    it('adds vendor prefixes', () => {
      const css = testTransformed({
        from: 'var styles = cssInJS({ foo: { flex: 1 } });',
        to:   'var styles = { foo: "test-styles-foo" };',
        options: { vendorPrefixes: true }
      });

      testStyleRule(css, 'test-styles-foo', 'flex: 1');
      testStyleRule(css, 'test-styles-foo', '-webkit-flex: 1');
      testStyleRule(css, 'test-styles-foo', '-ms-flex: 1');
    });
  });

  describe('with vendorPrefixes option set to an object', () => {
    it('adds vendor prefixes', () => {
      const css = testTransformed({
        from: 'var styles = cssInJS({ foo: { flex: 1 } });',
        to:   'var styles = { foo: "test-styles-foo" };',
        options: { vendorPrefixes: { remove: false } }
      });

      testStyleRule(css, 'test-styles-foo', 'flex: 1');
      testStyleRule(css, 'test-styles-foo', '-webkit-flex: 1');
      testStyleRule(css, 'test-styles-foo', '-ms-flex: 1');
    });<commit_msg>Update tests to support -webkit-box-flex (#17)<commit_after>import assert from 'assert';
import os from 'os';
import { transform } from 'babel-core';
import plugin from '../src/';
import { clearCache } from '../src/compressClassName';

describe('babel-plugin-css-in-js', () => {
  function makeOptions(options = {}) {
    return Object.assign({
      plugins: [
        [plugin, Object.assign({ bundleFile: 'tmp/bundle.css' }, options)]
      ],
      filename: 'test'
    }, options.babel);
  }

  function squish(str) {
    return str.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/g, ' ');
  }

  function testTransformed(spec) {
    const options = makeOptions(spec.options);
    const result  = transform(spec.from, options);
    const actual  = squish(result.code);
    let expected  = squish(spec.to);

    if (options.filename) {
      expected = '"use strict"; ' + expected;
    }

    assert.equal(actual, expected);

    return result.metadata.css;
  }

  function testStyleRule(css, className, rule) {
    assert(css);

    const hasClassNameWithRule = new RegExp(`\\.${className}\\s*\\{[^\\}]*?${rule}`);

    assert(hasClassNameWithRule.test(css));
  }

  it('does nothing if no "cssInJS" call is present', () => {
    let code = 'var styles = foo({ foo: { margin: 0 } });';

    const css = testTransformed({ from: code, to: code });

    assert.strictEqual(css, '');
  });

  it('throws if return value of "cssInJS" call is not assigned to a variable', () => {
    assert.throws(() => {
      testTransformed({
        from: `
          cssInJS({ foo: { margin: 0 } });
        `
      });
    }, /must be assigned to a variable/);
  });

  it('returns empty css if empty stylesheet provided', () => {
    const css = testTransformed({
      from: 'var styles = cssInJS({});',
      to:   'var styles = {};'
    });

    assert.strictEqual(css, '');
  });

  it('works without a babel filename option', () => {
    const css = testTransformed({
      from: 'var styles = cssInJS({ foo: { marginTop: -10, content: "foo" } });',
      to:   'var styles = { foo: "unknown-styles-foo" };',
      options: { babel: { filename: undefined } }
    });

    assert(css.indexOf('.unknown-styles-foo') > -1);
  });

  describe('with compressClassNames option set to true', () => {
    beforeEach(() => {
      clearCache({});
      clearCache({ cacheDir: os.tmpdir() });
    });

    it('compresses class names with memory cache', () => {
      const css = testTransformed({
        from: `
          var styles1 = cssInJS({ foo: { margin: 0 }, bar: { padding: 0 } });
          var styles2 = cssInJS({ xyz: { padding: 10 } });
        `,
        to: `
          var styles1 = { foo: "_0", bar: "_1" };
          var styles2 = { xyz: "_2" };
        `,
        options: {
          compressClassNames: true,
          cacheDir: null
        }
      });

      testStyleRule(css, '_0', 'margin: 0');
      testStyleRule(css, '_1', 'padding: 0');
      testStyleRule(css, '_2', 'padding: 10');
    });

    it('compresses class names with disk cache', () => {
      const css = testTransformed({
        from: `
          var styles1 = cssInJS({ foo: { margin: 0 }, bar: { padding: 0 } });
          var styles2 = cssInJS({ xyz: { padding: 10 } });
        `,
        to: `
          var styles1 = { foo: "_0", bar: "_1" };
          var styles2 = { xyz: "_2" };
        `,
        options: {
          compressClassNames: true,
          cacheDir: os.tmpdir()
        }
      });

      testStyleRule(css, '_0', 'margin: 0');
      testStyleRule(css, '_1', 'padding: 0');
      testStyleRule(css, '_2', 'padding: 10');
    });

    it('memoizes compressed class names between runs', () => {
      const css1 = testTransformed({
        from: `var styles = cssInJS({ foo: { margin: 0 } });`,
        to:   `var styles = { foo: "_0" };`,
        options: {
          compressClassNames: true,
          cacheDir: null,
          babel: { filename: 'foo.js' }
        }
      });

      testStyleRule(css1, '_0', 'margin: 0');

      const css2 = testTransformed({
        from: `var styles = cssInJS({ foo: { margin: 0 } });`,
        to:   `var styles = { foo: "_0" };`,
        options: {
          compressClassNames: true,
          cacheDir: null,
          babel: { filename: 'foo.js' }
        }
      });

      testStyleRule(css2, '_0', 'margin: 0');
    });
  });

  describe('with vendorPrefixes option set to true', () => {
    it('adds vendor prefixes', () => {
      const css = testTransformed({
        from: 'var styles = cssInJS({ foo: { flex: 1 } });',
        to:   'var styles = { foo: "test-styles-foo" };',
        options: { vendorPrefixes: true }
      });

      testStyleRule(css, 'test-styles-foo', 'flex: 1');
      testStyleRule(css, 'test-styles-foo', '-webkit-box-flex: 1');
      testStyleRule(css, 'test-styles-foo', '-ms-flex: 1');
    });
  });

  describe('with vendorPrefixes option set to an object', () => {
    it('adds vendor prefixes', () => {
      const css = testTransformed({
        from: 'var styles = cssInJS({ foo: { flex: 1 } });',
        to:   'var styles = { foo: "test-styles-foo" };',
        options: { vendorPrefixes: { remove: false } }
      });

      testStyleRule(css, 'test-styles-foo', 'flex: 1');
      testStyleRule(css, 'test-styles-foo', '-webkit-box-flex: 1');
      testStyleRule(css, 'test-styles-foo', '-ms-flex: 1');
    });
{'fraction_non_alphanumeric': 0.18249327021256845, 'fraction_numerical': 0.011510257124292211, 'mean_word_length': 2.299846860643185, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7608126', 'n_tokens_mistral': 3528, 'n_tokens_neox': 3367, 'n_words': 863}