<commit_before>require File.expand_path('../spec_helper', __FILE__)

module Rails
  def self.env
    self
  end

  def self.production?
    false
  end
end

describe Snogmetrics do
  before do
    @session = {}
    @context = Object.new
    @context.extend(Snogmetrics)
    allow(@context).to receive(:session).and_return(@session)
    allow(@context).to receive(:kissmetrics_api_key).and_return('abc123')
  end

  describe '#record' do
    it 'will output code that pushes an event with the specified name and properties' do
      @context.km.record('hello world', foo: 'bar')
      expect(@context.km.js).to include('_kmq.push(["record","hello world",{"foo":"bar"}]);')
    end

    it 'will output code that pushes an event with name only' do
      @context.km.record('foo')
      expect(@context.km.js).to include('_kmq.push(["record","foo"]);')
    end

    it 'will output code that pushes an event with properties only' do
      @context.km.record(foo: 'bar', plink: :plonk)
      expect(@context.km.js).to match(/_kmq.push\(\["record",\{(?:"foo":"bar","plink":"plonk"|"plink":"plonk","foo":"bar")\}\]\)/)
    end

    it 'complains if called without arguments' do
      expect(running { @context.km.record }).to raise_error(RuntimeError, 'Not enough arguments')
    end

    it 'complains if called with more than two arguments' do
      expect(running { @context.km.record(1, 2, 3) }).to raise_error(RuntimeError, 'Too many arguments')
    end

    it 'will output code that pushes events with the same name in the order they were recorded' do
      @context.km.record('An important event', p: 3)
      @context.km.record('An important event', p: 4)
      js = @context.km.js
      first = '_kmq.push(["record","An important event",{"p":3}]);'
      second = '_kmq.push(["record","An important event",{"p":4}]);'
      expect(js).to include(first)
      expect(js).to include(second)
      expect(js.index(first)).to be < js.index(second)
    end
  end

  describe '#trackClick' do
    it 'will output code that pushes an event with the specified name and properties' do
      @context.km.trackClick('tagid', 'hello world', foo: 'bar')
      expect(@context.km.js).to include('_kmq.push(["trackClick","tagid","hello world",{"foo":"bar"}]);')
    end

    it 'will output code that pushes an event with name only' do
      @context.km.trackClick('tagid', 'foo')
      expect(@context.km.js).to include('_kmq.push(["trackClick","tagid","foo"]);')
    end

    it 'will output code that pushes an event with properties only' do
      @context.km.trackClick('tagid', foo: 'bar', plink: :plonk)
      expect(@context.km.js).to match(/_kmq.push\(\["trackClick","tagid",\{(?:"foo":"bar","plink":"plonk"|"plink":"plonk","foo":"bar")\}\]\)/)
    end

    it 'complains if called without arguments' do
      expect(running { @context.km.trackClick }).to raise_error(ArgumentError)
    end

    it 'complains if called with selector only' do
      expect(running { @context.km.trackClick('tagid') }).to raise_error(RuntimeError, 'Not enough arguments')
    end

    it 'complains if called with more than three arguments' do
      expect(running { @context.km.trackClick('tagid', 'hello world', { foo: 'bar' }, '12') }).to raise_error(RuntimeError, 'Too many arguments')
    end
  end

  describe '#identify' do
    it 'will output code that pushes an identify call with the provided identity' do
      @context.km.identify('Phil')
      expect(@context.km.js).to include('_kmq.push(["identify","Phil"]);')
    end

    it 'will only output the last identity set' do
      @context.km.identify('Phil')
      @context.km.identify('Anne')
      @context.km.identify('Steve')
      expect(@context.km.js).not_to include('Phil')
      expect(@context.km.js).not_to include('Anne')
      expect(@context.km.js).to     include('Steve')
    end
  end

  describe '#set' do
    it 'will output code that pushes a set call with the provided experiment name and variant' do
      @context.km.set('My Awesome Experiment', 'variant_a')
      expect(@context.km.js).to include('_kmq.push(["set",{"My Awesome Experiment":"variant_a"}])')
    end
  end

  describe '#js' do
    context 'in production' do
      before do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
      end

      it 'outputs a JavaScript tag that loads the KISSmetrics API for the provided API key' do
        allow(@context).to receive(:kissmetrics_api_key).and_return('cab1ebeef')
        @context.km.identify('Phil')
        expect(@context.km.js).to include('scripts.kissmetrics.com/cab1ebeef.2.js')
      end
    end

    context 'overriding #use_fake_kissmetrics_api?' do
      it 'will do your bidding, and not be influenced by Rails.env' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:use_fake_kissmetrics_api?).and_return(true)
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
      end
    end

    context 'overriding #output_strategy with :console_log' do
      it 'outputs calls to console.log' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:output_strategy).and_return(:console_log)
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
        expect(@context.km.js).to include('console.dir')
      end
    end

    context 'overriding #output_strategy with :array' do
      it 'just stores calls in the _kmq array' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:output_strategy).and_return(:array)
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
        expect(@context.km.js).not_to include('console.dir')
      end
    end

    context 'overriding #output_strategy with :live' do
      it 'sends calls to KISSmetrics' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:output_strategy).and_return(:live)
        @context.km.identify('Joyce')
        expect(@context.km.js).to include('scripts.kissmetrics.com')
        expect(@context.km.js).not_to include('console.dir')
      end
    end

    context 'overriding #output_strategy with something else' do
      it 'raises' do
        allow(@context).to receive(:output_strategy).and_return(:something_else)
        expect do
          expect(@context.km.js).to include('scripts.kissmetrics.com')
        end.to raise_error(RuntimeError, 'Unknown KISSmetrics output strategy: something_else')
      end
    end

    it 'outputs javascript even if there are no events and no identity' do
      expect(@context.km.js).to include('kmq')
    end

    it 'outputs code that conditionally sets the _kmq variable' do
      @context.km.identify('Phil')
      expect(@context.km.js).to include('var _kmq = _kmq || [];')
    end
<commit_msg>Add additional tests for output_strategy accessor<commit_after>require File.expand_path('../spec_helper', __FILE__)

module Rails
  def self.env
    self
  end

  def self.production?
    false
  end
end

describe Snogmetrics do
  before do
    @session = {}
    @context = Object.new
    @context.extend(Snogmetrics)
    allow(@context).to receive(:session).and_return(@session)
  end

  describe '#record' do
    it 'will output code that pushes an event with the specified name and properties' do
      @context.km.record('hello world', foo: 'bar')
      expect(@context.km.js).to include('_kmq.push(["record","hello world",{"foo":"bar"}]);')
    end

    it 'will output code that pushes an event with name only' do
      @context.km.record('foo')
      expect(@context.km.js).to include('_kmq.push(["record","foo"]);')
    end

    it 'will output code that pushes an event with properties only' do
      @context.km.record(foo: 'bar', plink: :plonk)
      expect(@context.km.js).to match(/_kmq.push\(\["record",\{(?:"foo":"bar","plink":"plonk"|"plink":"plonk","foo":"bar")\}\]\)/)
    end

    it 'complains if called without arguments' do
      expect(running { @context.km.record }).to raise_error(RuntimeError, 'Not enough arguments')
    end

    it 'complains if called with more than two arguments' do
      expect(running { @context.km.record(1, 2, 3) }).to raise_error(RuntimeError, 'Too many arguments')
    end

    it 'will output code that pushes events with the same name in the order they were recorded' do
      @context.km.record('An important event', p: 3)
      @context.km.record('An important event', p: 4)
      js = @context.km.js
      first = '_kmq.push(["record","An important event",{"p":3}]);'
      second = '_kmq.push(["record","An important event",{"p":4}]);'
      expect(js).to include(first)
      expect(js).to include(second)
      expect(js.index(first)).to be < js.index(second)
    end
  end

  describe '#trackClick' do
    it 'will output code that pushes an event with the specified name and properties' do
      @context.km.trackClick('tagid', 'hello world', foo: 'bar')
      expect(@context.km.js).to include('_kmq.push(["trackClick","tagid","hello world",{"foo":"bar"}]);')
    end

    it 'will output code that pushes an event with name only' do
      @context.km.trackClick('tagid', 'foo')
      expect(@context.km.js).to include('_kmq.push(["trackClick","tagid","foo"]);')
    end

    it 'will output code that pushes an event with properties only' do
      @context.km.trackClick('tagid', foo: 'bar', plink: :plonk)
      expect(@context.km.js).to match(/_kmq.push\(\["trackClick","tagid",\{(?:"foo":"bar","plink":"plonk"|"plink":"plonk","foo":"bar")\}\]\)/)
    end

    it 'complains if called without arguments' do
      expect(running { @context.km.trackClick }).to raise_error(ArgumentError)
    end

    it 'complains if called with selector only' do
      expect(running { @context.km.trackClick('tagid') }).to raise_error(RuntimeError, 'Not enough arguments')
    end

    it 'complains if called with more than three arguments' do
      expect(running { @context.km.trackClick('tagid', 'hello world', { foo: 'bar' }, '12') }).to raise_error(RuntimeError, 'Too many arguments')
    end
  end

  describe '#identify' do
    it 'will output code that pushes an identify call with the provided identity' do
      @context.km.identify('Phil')
      expect(@context.km.js).to include('_kmq.push(["identify","Phil"]);')
    end

    it 'will only output the last identity set' do
      @context.km.identify('Phil')
      @context.km.identify('Anne')
      @context.km.identify('Steve')
      expect(@context.km.js).not_to include('Phil')
      expect(@context.km.js).not_to include('Anne')
      expect(@context.km.js).to     include('Steve')
    end
  end

  describe '#set' do
    it 'will output code that pushes a set call with the provided experiment name and variant' do
      @context.km.set('My Awesome Experiment', 'variant_a')
      expect(@context.km.js).to include('_kmq.push(["set",{"My Awesome Experiment":"variant_a"}])')
    end
  end

  describe '#js' do
    context 'in production' do
      before do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
      end

      it 'outputs a JavaScript tag that loads the KISSmetrics API for the provided API key' do
        Snogmetrics.kissmetrics_api_key = 'cab1ebeef'
        @context.km.identify('Phil')
        expect(@context.km.js).to include('scripts.kissmetrics.com/cab1ebeef.2.js')
      end
    end

    context 'overriding #use_fake_kissmetrics_api?' do
      it 'will do your bidding, and not be influenced by Rails.env' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:use_fake_kissmetrics_api?).and_return(true)
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
      end
    end

    context 'overriding #output_strategy with :console_log' do
      it 'outputs calls to console.log' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:output_strategy).and_return(:console_log)
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
        expect(@context.km.js).to include('console.dir')
      end

      it 'outputs calls to console.log when configured with accessor' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        Snogmetrics.output_strategy = :console_log
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
        expect(@context.km.js).to include('console.dir')
      end
    end

    context 'overriding #output_strategy with :array' do
      it 'just stores calls in the _kmq array' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:output_strategy).and_return(:array)
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
        expect(@context.km.js).not_to include('console.dir')
      end

      it 'just stores calls in the _kmq array when configured with accessor' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        Snogmetrics.output_strategy = :array
        @context.km.identify('Joyce')
        expect(@context.km.js).not_to include('scripts.kissmetrics.com')
        expect(@context.km.js).not_to include('console.dir')
      end
    end

    context 'overriding #output_strategy with :live' do
      it 'sends calls to KISSmetrics' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        allow(@context).to receive(:output_strategy).and_return(:live)
        @context.km.identify('Joyce')
        expect(@context.km.js).to include('scripts.kissmetrics.com')
        expect(@context.km.js).not_to include('console.dir')
      end

      it 'sends calls to KISSmetrics when configured with accessor' do
        allow(Rails).to receive(:env).and_return(double('env', production?: true))
        Snogmetrics.output_strategy = :live
        @context.km.identify('Joyce')
        expect(@context.km.js).to include('scripts.kissmetrics.com')
        expect(@context.km.js).not_to include('console.dir')
      end
    end

    context 'overriding #output_strategy with something else' do
      it 'raises' do
        allow(@context).to receive(:output_strategy).and_return(:something_else)
        expect do
          expect(@context.km.js).to include('scripts.kissmetrics.com')
        end.to raise_error(RuntimeError, 'Unknown KISSmetrics output strategy: something_else')
      end
    end

    it 'outputs javascript even if there are no events and no identity' do
      expect(@context.km.js).to include('kmq')
    end

    it 'outputs code that conditionally sets the _kmq variable' do
      @context.km.identify('Phil')
      expect(@context.km.js).to include('var _kmq = _kmq || [];')
    end

{'fraction_non_alphanumeric': 0.1438423645320197, 'fraction_numerical': 0.0017733990147783252, 'mean_word_length': 3.4261627906976746, 'pattern_counts': {'":': 26, '<': 5, '<?xml version=': 0, '>': 3, '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': '4117434', 'n_tokens_mistral': 4779, 'n_tokens_neox': 4633, 'n_words': 1186}