Extending Spectacular

Snake Case Syntax

All the exposed methods are provided both with camelCase and snake_case syntax. By convention, JavaScript use the camel case form, but some people writing CoffeeScript for nodejs often use the snake case form. Spectacular support both.

You can define any matcher, or helper, or aliases, with either the snake case or camel case form, the alternative will be also added to the global object.

For instance, the sharedExample is also available through shared_example.

You can find below a table with all the snake case equivalent:

afterNo differences
beforeNo differences
beWithinbe_within
chainNo differences
containsNo differences
contextNo differences
createWithcreate_with
dependsOndepends_on
describeNo differences
descriptionNo differences
equalNo differences
existNo differences
expectNo differences
factoryNo differences
factoryMixinfactory_mixin
failNo differences
failureMessageForShouldfailure_message_for_should
failureMessageForShouldntfailure_message_for_shouldnt
fixturePathfixture_path
fixturesNo differences
givenNo differences
have.selectorNo differences
haveNo differences
haveBeenCalled.withhave_been_called.with
haveBeenCalledhave_been_called
itNo differences
itBehavesLikeit_behaves_like
itsNo differences
itShouldit_should
itsInstanceits_instance
itsReturnits_return
matchNo differences
matchNo differences
pendingNo differences
registerFixtureHandlerregister_fixture_handler
setNo differences
shouldNo differences
shouldntNo differences
skipNo differences
specifyNo differences
spy.argsForCallspy.args_for_call
spyOn(...).andCallFakespy_on(...).and_call_fake
spyOn(...).andCallThroughspy_on(...).and_call_trough
spyOn(...).andReturnsspy_on(...).and_returns
spyOnspy_on
subjectNo differences
successNo differences
takesNo differences
theNo differences
throwAnError(msg).inContextthrow_an_error(msg).in_context
throwAnError(msg).withthrow_an_error(msg).with
throwAnErrorthrow_an_error
traitNo differences
whenPasswhen_pass
withArgumentswith_arguments
withParameterswith_parameters
xcontextNo differences
xdescribeNo differences
xitNo differences

You can also snakify/camelize your own objects using the utils.snakify or utils.camelize methods:

myObject =
  someMethod: ->
  someOtherMethod: ->

utils.snakify myObject

Will gives you an object such as:

myObject =
  someMethod: ->
  someOtherMethod: ->
  some_method: ->
  some_other_method: ->

Matchers

Matchers are defined with the spectacular.matcher function. It generates an object with a match method that should return a boolean value corresponding to the assertion result.

spectacular.matcher 'returnSomething', ->
  match (actual) -> actual() isnt null

  description -> "return something"

  failureMessageForShould message = "Expected #{@actual} to #{@description}"

# Usage:
it -> should returnSomething

The matcher receive a string containing ' not' if the matcher was passed to shouldnt or expect(...).not.to.

If an exception is raised during the matcher execution, the example will be marked as errored instead of failure.

You can create parameterizable matcher by calling the takes function in the matcher definition block.

spectacular.matcher 'parameterizableMatcher', ->
  takes 'value1', 'value2'

  match -> @value1 and @value2

  description -> 'parameterizableMatcher description'

  failureMessageForShould -> 'parameterizableMatcher message'

# Usage:
it -> should parameterizableMatcher(value1, value2)

The parameters defined with takes are then stored in the matcher instance with the provided names. The takes function accept a slat argument such as values.... In that case, the splat must be the sole argument.

It's possible to run code on the initialization of a matcher:

spectacular.matcher 'matcherWithInit', ->
  init -> # do some setup such creating composed objects

  match (actual) -> @composedObject.match actual

  description -> 'matcher with init description'

  failureMessageForShould -> 'matcher with init message'

# Usage:
it -> should matcherWithInit(value1, value2)

You can also add chaining methods with the chain function:

spectacular.matcher 'chainableMatcher', ->
  takes 'value1'

  chain 'with', (@value2) ->

  match -> @value1 and @value2

  description -> 'chainableMatcher description'

  failureMessageForShould -> 'chainableMatcher message'

# Usage:
it -> should chainableMatcher(value1).with(value2)

Asynchronous Matchers

Matchers can be asynchronous, in that case they should return a promise instead of a boolean value. The default timeout for asynchronous matchers is 5000ms, it can be changed by setting the timeout in the matcher block.

spectacular.matcher 'asyncMatcher', ->
  timeout 1000
  match (actual, notText) ->

    promise = new spectacular.Promise

    setTimeout (-> promise.resolve actual isnt null), 100

    promise

  description -> 'should match asynchronously'
  failureMessageForShould -> 'Expected to match asynchronously'

If the promise is rejected, the example is marked as errored.

Fixtures Handlers

Spectacular support by default 3 fixtures format: json, html and dom.

However you can quickly extend Spectacular with new fixtures handlers using the registerFixtureHandler:

registerFixtureHandler 'ext', (content) ->
  # do something with the content

The value returned by the handler block will be used as the fixture in specs.