<commit_before>_ = require('../util/lodash-wrap')

store = require('./index')
callsStore = require('./calls')
argsMatch = require('../args-match')
callback = require('../matchers/callback')
config = require('../config')
log = require('../log')

module.exports =
  add: (testDouble, args, stubbedValues, config) ->
    store.for(testDouble).stubbings.push({callCount: 0, stubbedValues, args, config})

  invoke: (testDouble, actualArgs) ->
    return unless stubbing = stubbingFor(testDouble, actualArgs)
    executePlan(stubbing, actualArgs)

  for: (testDouble) ->
    store.for(testDouble).stubbings

stubbingFor = (testDouble, actualArgs) ->
  _.findLast store.for(testDouble).stubbings, (stubbing) ->
    isSatisfied(stubbing, actualArgs)

executePlan = (stubbing, actualArgs) ->
  Promise = config().promiseConstructor
  value = stubbedValueFor(stubbing)
  stubbing.callCount += 1
  invokeCallbackFor(stubbing, actualArgs)
  switch stubbing.config.plan
    when "thenReturn" then value
    when "thenDo" then value(actualArgs...)
    when "thenThrow" then throw value
    when "thenResolve"
      ensurePromise(Promise)
      new Promise((resolve) -> resolve(value))
    when "thenReject"
      ensurePromise(Promise)
      new Promise((resolve, reject) -> reject(value))

invokeCallbackFor = (stubbing, actualArgs) ->
  return unless _.some(stubbing.args, callback.isCallback)
  _.each stubbing.args, (expectedArg, i) ->
    return unless callback.isCallback(expectedArg)
    args = callbackArgs stubbing, expectedArg
    callCallback stubbing.config, actualArgs[i], args

callbackArgs = (stubbing, expectedArg) ->
  if expectedArg.args?
    expectedArg.args
  else if stubbing.config.plan == 'thenCallback'
    stubbing.stubbedValues
  else
    []

callCallback = ({defer, delay}, callback, args) ->
  if defer
    _.defer(callback, args...)
  else if delay
    _.delay(callback, delay, args...)
  else
    callback(args...)

stubbedValueFor = (stubbing) ->
  if stubbing.callCount < stubbing.stubbedValues.length
    stubbing.stubbedValues[stubbing.callCount]
  else
    _.last(stubbing.stubbedValues)

isSatisfied = (stubbing, actualArgs) ->
  argsMatch(stubbing.args, actualArgs, stubbing.config) &&
    hasTimesRemaining(stubbing)<commit_msg>style points<commit_after>_ = require('../util/lodash-wrap')

store = require('./index')
callsStore = require('./calls')
argsMatch = require('../args-match')
callback = require('../matchers/callback')
config = require('../config')
log = require('../log')

module.exports =
  add: (testDouble, args, stubbedValues, config) ->
    store.for(testDouble).stubbings.push({callCount: 0, stubbedValues, args, config})

  invoke: (testDouble, actualArgs) ->
    return unless stubbing = stubbingFor(testDouble, actualArgs)
    executePlan(stubbing, actualArgs)

  for: (testDouble) ->
    store.for(testDouble).stubbings

stubbingFor = (testDouble, actualArgs) ->
  _.findLast store.for(testDouble).stubbings, (stubbing) ->
    isSatisfied(stubbing, actualArgs)

executePlan = (stubbing, actualArgs) ->
  Promise = config().promiseConstructor
  value = stubbedValueFor(stubbing)
  stubbing.callCount += 1
  invokeCallbackFor(stubbing, actualArgs)
  switch stubbing.config.plan
    when "thenReturn" then value
    when "thenDo" then value(actualArgs...)
    when "thenThrow" then throw value
    when "thenResolve"
      ensurePromise(Promise)
      new Promise((resolve) -> resolve(value))
    when "thenReject"
      ensurePromise(Promise)
      new Promise((resolve, reject) -> reject(value))

invokeCallbackFor = (stubbing, actualArgs) ->
  return unless _.some(stubbing.args, callback.isCallback)
  _.each stubbing.args, (expectedArg, i) ->
    return unless callback.isCallback(expectedArg)
    args = callbackArgs(stubbing, expectedArg)
    callCallback(stubbing.config, actualArgs[i], args)

callbackArgs = (stubbing, expectedArg) ->
  if expectedArg.args?
    expectedArg.args
  else if stubbing.config.plan == 'thenCallback'
    stubbing.stubbedValues
  else
    []

callCallback = (config, callback, args) ->
  if config.defer
    _.defer(callback, args...)
  else if config.delay
    _.delay(callback, delay, args...)
  else
    callback(args...)

stubbedValueFor = (stubbing) ->
  if stubbing.callCount < stubbing.stubbedValues.length
    stubbing.stubbedValues[stubbing.callCount]
  else
    _.last(stubbing.stubbedValues)

isSatisfied = (stubbing, actualArgs) ->
  argsMatch(stubbing.args, actualArgs, stubbing.config) &&
    hasTimesRemaining(stubbing)
{'fraction_non_alphanumeric': 0.1305118546421449, 'fraction_numerical': 0.0008863283846665189, 'mean_word_length': 4.170675830469645, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, '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': '5494943', 'n_tokens_mistral': 1383, 'n_tokens_neox': 1428, 'n_words': 299}