{"id":20758930,"url":"https://github.com/crismali/magic_lamp","last_synced_at":"2025-04-09T14:09:08.626Z","repository":{"id":18054080,"uuid":"21107783","full_name":"crismali/magic_lamp","owner":"crismali","description":"Gets your Rails templates/json into your JavaScript specs.","archived":false,"fork":false,"pushed_at":"2022-12-13T22:47:42.000Z","size":502,"stargazers_count":67,"open_issues_count":9,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T07:44:39.862Z","etag":null,"topics":["fixtures","javascript","javascript-specs","rails","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crismali.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-06-22T22:48:34.000Z","updated_at":"2023-09-08T16:48:25.000Z","dependencies_parsed_at":"2023-01-13T19:38:05.959Z","dependency_job_id":null,"html_url":"https://github.com/crismali/magic_lamp","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crismali%2Fmagic_lamp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crismali%2Fmagic_lamp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crismali%2Fmagic_lamp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crismali%2Fmagic_lamp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crismali","download_url":"https://codeload.github.com/crismali/magic_lamp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054199,"owners_count":21039952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fixtures","javascript","javascript-specs","rails","ruby"],"created_at":"2024-11-17T09:54:15.188Z","updated_at":"2025-04-09T14:09:08.602Z","avatar_url":"https://github.com/crismali.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"Magic Lamp\n=========\n[![Gem Version](https://badge.fury.io/rb/magic_lamp.svg)](http://badge.fury.io/rb/magic_lamp)\n[![Build Status](https://travis-ci.org/crismali/magic_lamp.svg?branch=master)](https://travis-ci.org/crismali/magic_lamp)\n\nMagic Lamp helps you get your Rails templates into your JavaScript tests. This means that way your JavaScript tests break\nif you change your templates _and_ you don't have to create so many fixtures. Plus, it lets you test your views in JavaScript.\nAll you have to do is set up your data just like you would in a controller.\n\nTable of Contents\n-----------------\n1. [Installation](#installation)\n2. [Basic Usage](#basic-usage)\n3. [Where the files go](#where-the-files-go)\n4. [Tasks](#tasks)\n5. [Ruby API](#ruby-api)\n6. [JavaScript API](#javascript-api)\n7. [Errors](#errors)\n8. [Sweet Aliases](#sweet-aliases)\n9. [Contributing](#contributing)\n\nInstallation\n------------\n\nAdd this line to your application's `Gemfile`:\n```ruby\n  gem \"magic_lamp\"\n```\nAnd then execute:\n\n    $ bundle install\n\nThen paste `mount MagicLamp::Genie, at: \"/magic_lamp\" if defined?(MagicLamp)` into your `config/routes.rb` like so:\n```ruby\nRails.application.routes.draw do\n  # ...\n  mount MagicLamp::Genie, at: \"/magic_lamp\" if defined?(MagicLamp)\n  # ...\nend\n```\nThis mounts the Magic Lamp engine in your app.\n\nThen drop this:\n```js\n//= require magic_lamp\n```\nat the top of your `spec_helper.js` (assuming you're using JavaScript spec runner for Rails that allows the use of Sprockets directives).\n\nIf your JavaScript test runner doesn't support XHR requests, you can drop this in instead:\n\n```js\n//= require magic_lamp\n//= require magic_lamp/all_fixtures\n```\n\n`//= require magic_lamp/all_fixtures` will load all of your fixtures without making any XHR requests. \n\n**Note:** when loading your fixtures via Sprockets directives you will likely want to disable Sprockets caching in whatever environment your JavaScript tests are running. You can do so by putting the following in the appropriate environment config file:\n\n```ruby\nconfig.assets.configure do |env|\n  env.cache = ActiveSupport::Cache.lookup_store(:null_store)\nend\n```\n\nNow you've got the basic setup.\n\n### Debugging\nVisit `/magic_lamp/lint` in your browser to lint your fixtures. You can also run `rake magic_lamp:lint` (or `rake mll` for short) to lint your fixtures from the command line.\n\n### Loading Helpers\n\nSimply `load` your helpers in the `magic_lamp_config.rb` file like so:\n\n```ruby\n# in magic_lamp_config.rb\nDir[Rails.root.join(\"spec\", \"support\", \"magic_lamp_helpers/**/*.rb\")].each { |f| load f }\n```\n\n### Supported test runners\nMagic Lamp has been shown to work with:\n\n* [Jasmine Rails](https://github.com/searls/jasmine-rails)\n* [Jasmine](https://github.com/jasmine/jasmine-gem)\n* [Konacha](https://github.com/jfirebaugh/konacha)\n* [Teaspoon](https://github.com/modeset/teaspoon)\n\nIt will likely work with any test runner that supports XHR requests or Sprockets directives.\n\n### With Database Cleaner\n\nYou don't need [Database Cleaner](https://github.com/DatabaseCleaner/database_cleaner) to use this gem, but this is probably the setup most people want.\n\nFirst make sure you have Database Cleaner installed, then you'll want to do something like this:\n```ruby\nrequire \"database_cleaner\"\n\nMagicLamp.configure do |config|\n\n  DatabaseCleaner.strategy = :transaction\n\n  config.before_each do\n    DatabaseCleaner.start\n  end\n\n  config.after_each do\n    DatabaseCleaner.clean\n  end\nend\n```\nin a file called `magic_lamp_config.rb` which you can place anywhere in your `spec` or `test` directories.\n\nThis way you can take advantage of `after_create` callbacks for your fixture setup without polluting\nyour database every time you run your JavaScript specs.\n\n### With FactoryGirl\n\nIf you're using FactoryGirl, Magic Lamp will call `FactoryGirl.reload` for you to save you some autoloader pain.\n\nBasic Usage\n-----------\nMagic Lamp will load all files in your `spec` or `test` directory that end with `_lamp.rb` (your app's\n\"lamp files). I'd recommend starting with a single `magic_lamp.rb` file and breaking it into smaller\nfiles once it gets unwieldy (one for each controller would be a good approach).\n\nIn your lamp files you just call [`MagicLamp.fixture`](#fixture) like so:\n```ruby\nMagicLamp.fixture do\n  @order = Order.new\n  render partial: \"orders/form\"\nend\n```\nInside the block you pass to `fixture` you're in the scope of a controller so you\ncan set up any instance variables your templates depend on. In this case we're\nusing the default controller which is your `ApplicationController`. We're also\nusing the default name for the fixture which is whatever `render` receives to\nidentify the template (ie the symbol or string argument to `render` or\nwhatever is at the `:template` or `:partial` key in the argument hash).\n\n`render` here also works normally except that it won't render the layout by default.\n\nThen in your JavaScript you can call [`load`](#load):\n```js\nbeforeEach(function() {\n  MagicLamp.load(\"orders/form\");\n});\n```\nwhich will put the `orders/form` partial in a div with a class of `magic-lamp` (this all happens synchronously).\nThen you can go nuts testing your JavaScript against your actual template. If you'd like to only make\none request for your templates, simply call [`MagicLamp.preload();`](#preload) in your `spec_helper.js` to\npopulate Magic Lamp's cache.\n\n### Loading multiple templates\n\nJust pass more fixture names to `MagicLamp.load` and it will load them all. For example:\n```js\n  beforeEach(function() {\n    MagicLamp.load(\"orders/sidebar\", \"orders/form\");\n  });\n```\n\nwith a sidebar template/partial that looks like this:\n```html\n  \u003cdiv class=\"sidebar content\"\u003eLinks!\u003c/div\u003e\n```\n\nand a form template/partial that looks like this:\n```html\n  \u003cdiv class=\"form content\"\u003eInputs!\u003c/div\u003e\n```\n\nwill yield:\n```html\n  \u003cdiv class=\"magic-lamp\"\u003e\n    \u003cdiv class=\"sidebar content\"\u003eLinks!\u003c/div\u003e\n    \u003cdiv class=\"form content\"\u003eInputs!\u003c/div\u003e\n  \u003c/div\u003e\n```\n\n### Loading JSON fixtures and arbitrary strings\nIf you pass a block to `fixture` that does not invoke `render`, Magic Lamp will assume that you want the `to_json` representation of the return value of the block as your fixture (Magic Lamp will call this for you). If the return value is already a string, then Magic Lamp will return that string as is. In your JavaScript `MagicLamp.loadJSON` will return the `JSON.parse`d string while `MagicLamp.loadRaw` will return the string as is (you can also use `loadRaw` get the string version of a template rendered with `render` without Magic Lamp appending it to the DOM. `loadJSON` also won't interact with the DOM).\n\nWhen sending down JSON or arbitrary strings, you must provide the fixture with a name since inferring one is impossible. \n\nIt's also good to remember that in the fixture block that even though the controller isn't rendering anything for us, the block is still scoped to the given controller which gives us access to any controller methods we might want to use to massage our data structures.\n\nFor example: \n\n```ruby\nMagicLamp.define(controller: OrdersController) do\n  fixture(name: \"some_json\") do\n    OrderSerializer.new(Order.new(price: 55))\n  end\n\n  fixture(name: \"some_arbitrary_string\") do\n    some_method_on_the_controller_that_returns_a_string(\"Just some string\")\n  end\nend\n```\n\nThen in your JavaScript:\n\n```js\nbeforeEach(function() {\n  var jsonObject = MagicLamp.loadJSON(\"orders/some_json\");\n  var someString = MagicLamp.loadRaw(\"orders/some_arbitrary_string\");\n});\n```\n\n### A few more examples\nHere we're specifying which controller should render the template via the arguments hash\nto `fixture`. This gives us access to helper methods in the `fixture` block\nand in the template. It also means we don't need a fully qualified path to the rendered template\nor partial.\n\nSince we didn't specify the name of our fixture and we're not using the `ApplicationController`\nto render the template the fixture will be named \"orders/order\".\n\nWe're also taking advantage of `render`'s `:collection` option.\n```ruby\nMagicLamp.fixture(controller: OrdersController) do\n  orders = 3.times.map { Order.new }\n  render partial: \"order\", collection: orders\nend\n```\n\nHere we're specifying a name with the `:name` option that's passed to `fixture`.\nThis way we can load the fixture in our JavaScript with `MagicLamp.load(\"custom/name\")` instead\nof the default `MagicLamp.load(\"orders/foo\")`. Custom names for fixtures must be url safe strings. We're also extending the controller and its view with the `AuthStub` module to stub some methods that we don't want executing in our fixtures.\n```ruby\nMagicLamp.fixture(name: \"custom/name\", extend: AuthStub) do\n  render \"orders/foo\"\nend\n```\n\nHere we're specifying both a controller and custom name. We're also setting the `params[:foo]`\nmostly to demonstrate that we have access to all of the usual controller methods.\n```ruby\nMagicLamp.fixture(controller: OrdersController, name: \"other_custom_name\") do\n  params[:foo] = \"test\"\n  render :foo\nend\n```\n\n### Drying up your fixtures\nIf you have several fixtures that depend on the same setup (same controller, extensions, etc), you can use the `define` method to dry things up:\n\n```ruby\nMagicLamp.define(controller: OrdersController, extend: AuthStub) do\n  fixture do # orders/new\n    @order = Order.new\n    render :new\n  end\n\n  fixture(name: \"customized_new\") do # orders/customized_new\n    session[:custom_user_info] = \"likes movies\"\n    @order = Order.new\n    render :new\n  end\n\n  fixture do # orders/form\n    @order = Order.new\n    render partial: \"form\"\n  end\n\n  define(namespace: \"errors\", extend: SomeErrorHelpers) do\n    fixture(name: \"form_without_price\") do # orders/errors/form_without_price\n      @order = Order.new\n      @order.errors.add(:price, \"can't be blank\")\n      render partial: \"form\"\n    end\n\n    fixture do # orders/errors/form\n      @order = Order.new\n      @order.errors.add(:address, \"can't be blank\")\n      render partial: \"form\"\n    end\n  end\nend\n```\n\nWhere the files go\n------------------------\n### Config File\nMagic Lamp first loads the `magic_lamp_config.rb` file. It can be anywhere in your `spec` or `test`\ndirectory but it's not required.\n### Lamp files\nMagic Lamp will load any files in your `spec` or `test` directory that end with `_lamp.rb`.\n\nTasks\n-----\n### fixture_names\nCall `rake magic_lamp:fixture_names` (or `rake mlfn`) to see a list of all of your app's fixture names.\n### lint\nCall `rake magic_lamp:lint` (or `rake mll`) to see if there are any errors when registering or rendering your fixtures.\n\nRuby API\n--------\n### fixture\n(also aliased to `register_fixture` and `register`)\n\nIt requires a block that is invoked in the context of a controller. If `render` is called, it renders the specified template or partial the way the controller normally would minus the layout. If you'd like a particular layout to be rendered simply specify it when you call `render`:\n\n```ruby\nrender :index, layout: \"admin\"\n```\n\n**Note:** Rendering the layout could be useful under some circumstances, but it is important to be aware that things will get weird if you use MagicLamp to load and entire HTML document. Especially if it contains `script` tags to your JavaScript.\n\nIf `render` is not called in the block then MagicLamp will render the `to_json` representation of the return value of the block unless the return value is already a string. In that case, the string is rendered as is.\n\nIt also takes an optional hash of arguments. The arguments hash recognizes:\n* `:controller`\n  * specifies any controller class that you'd like to have render the template or partial or have the block scoped to.\n  * if specified it removes the need to pass fully qualified paths to templates to `render`\n  * the controller's name becomes the default `namespace`, ie `OrdersController` provides a default namespace of `orders` resulting in a template named `orders/foo`\n* `:name`\n  * whatever you'd like name the fixture.\n  * Specifying this option also prevents the block from being executed twice which could be a performance win. See [configure](#configure) for more.\n  * this is required when you want to send down JSON or arbitrary strings.\n* `:extend`\n  * takes a module or an array of modules\n  * extends the controller and view context (via Ruby's `extend`)\nAlso note that only symbol keys are recognized.\n\n`fixture` will also execute any callbacks you've specified. See [configure](#configure) for more.\n\nExample:\n```ruby\nMagicLamp.fixture(name: \"foo\", controller: OrdersController) do\n  @order = Order.new\n  render partial: \"form\"\nend\n```\n\n### define\nAllows you scope groups of fixtures with defaults and can be nested arbitrarily. It takes an optional hash and a required block. The hash accepts the following options:\n* `:controller`\n  * specifies any controller class that you'd like to have render the template or partial.\n  * if specified it removes the need to pass fully qualified paths to templates to `render`\n  * the controller's name becomes the default `namespace` if no namespace is provided, ie `OrdersController` provides a default namespace of `orders` resulting in a template named `orders/foo`\n* `:name`\n  * whatever you'd like name the fixture.\n  * Specifying this option also prevents the block from being executed twice which could be a performance win. See [configure](#configure) for more.\n* `:extend`\n  * takes a module or an array of modules\n  * extends the controller and view context (via Ruby's `extend`)\n* `:namespace`\n  * namespaces all fixtures defined within it\n  * overrides the default controller namespace if passed\nAlso note that only symbol keys are recognized.\n\nInside of the block you can nest more calls to `define` and create fixtures\nvia the `fixture` method or one of its aliases.\n\nExample:\n```ruby\nmodule DefinesFoo\n  def foo\n    \"foo!\"\n  end\nend\n\nmodule AlsoDefinesFoo\n  def foo\n    \"also foo!\"\n  end\nend\n\nMagicLamp.define(controller: OrdersController, extend: DefinesFoo) do\n\n  fixture do # orders/edit\n    foo #=\u003e \"foo!\"\n    @order = Order.create!\n    render :edit\n  end\n\n  fixture do # orders/new\n    foo #=\u003e \"foo!\"\n    @order = Order.new\n    render :new\n  end\n\n  define(namespace: \"errors\", extend: AlsoDefinesFoo) do\n\n    fixture do # orders/errors/edit\n      foo #=\u003e \"also foo!\"\n      @order = Order.create!\n      @order.errors.add(:price, \"Can't be negative\")\n      render :edit\n    end\n\n    fixture(extend: DefinesFoo) do # orders/errors/new\n      foo #=\u003e \"foo!\"\n      @order = Order.new\n      @order.errors.add(:price, \"Can't be negative\")\n      render :new\n    end\n  end\nend\n```\n\n### configure\nIt requires a block to which it yields the configuration object. Here you can set:\n* `before_each`\n  * takes a block\n  * defaults to `nil`\n  * called before each block you pass to `fixture` is executed\n  * note: if you call it a second time with a second block, only the second block will be executed\n* `after_each`\n  * takes a block\n  * defaults to `nil`\n  * called after each block you pass to `fixture` is executed\n  * note: if you call it a second time with a second block, only the second block will be executed\n* `global_defaults`\n  * can be set to a hash of default options that every fixture generated will inherit from. Options passed to `define` and `fixture` take precedence.\n  * accepts all of the keys `define` accepts\n* `infer_names`\n  * defaults to `true`\n  * if set to true, Magic Lamp will try to infer the name of the fixture when not provided with a name parameter.\n  * if set to false, the name parameter becomes required for `MagicLamp.fixture` (this can be done to improve performance or force your team to be more explicit)\n\nExample:\n\n```ruby\n# spec/support/magic_lamp/helpers/auth_stub.rb\nmodule AuthStub\n  def current_user\n    @current_user ||= User.create!(\n      email: \"foo@example.com\",\n      password: \"password\"\n    )\n  end\nend\n\n# spec/magic_lamp_config.rb (can be anywhere in /spec)\nMagicLamp.configure do |config|\n\n  Dir[Rails.root.join(\"spec\", \"support\", \"magic_lamp_helpers/**/*.rb\")].each { |f| load f }\n\n  # if you want to require the name parameter for the `fixture` method\n  config.infer_names = false\n\n  config.global_defaults = { extend: AuthStub }\n\n  config.before_each do\n    puts \"I appear before the block passed to `fixture` executes!\"\n  end\n\n  config.after_each do\n    puts \"I appear after the block passed to `fixture` executes!\"\n  end\nend\n```\n\nJavaScript API\n--------------\n### clean\nCalling `MagicLamp.clean()` will remove the Magic Lamp fixture container from the page.\n\nIf you don't want any dom elements from a fixture hanging around between specs, throw it\nin a global `afterEach` block. Calling it with nothing to clean won't result in an error.\n\nExample:\n```js\n  afterEach(function() {\n    MagicLamp.clean();\n  });\n```\n### load\nCall `MagicLamp.load` to load a fixture. It requires the name of the fixture and which will be loaded into a `div` with a class of `magic-lamp`. It will destroy the previous fixture container if present so you never end up with duplicate fixture containers or end up with dom elements from previous loads. It will hit the network only on the first request for a given\nfixture. If you never want `load` to hit the network, call [`MagicLamp.preload()`](#preload) or use `//= require magic_lamp/all_fixtures` before your specs.\n\nYou can load multiple fixtures into the dom at the same time by simply passing more arguments to `load`. \n\nThe call to get your template is completely synchronous.\n\nExample:\n```js\n  beforeEach(function() {\n    MagicLamp.load(\"orders/foo\");\n  });\n\n  // or if you wanted multiple fixtures...\n\n  beforeEach(function() {\n    MagicLamp.load(\"orders/foo\", \"orders/bar\", \"orders/foo\", \"orders/baz\");\n  });\n```\n### loadJSON\nReturns the `JSON.parse`d version of the fixture. It's a convenience method for `JSON.parse(MagicLamp.loadRaw('some_json_fixture'));`. Look [here](#loading-json-fixtures-and-arbitrary-strings) for more.\n### loadRaw\nReturns the template, partial, JSON, or string as a raw string. Look [here](#loading-json-fixtures-and-arbitrary-strings) for more.\n### preload\nCall `MagicLamp.preload` to load all of your templates into MagicLamp's cache. This means you'll\nonly hit the network once, so the rest of your specs will be quicker and you can go wild stubbing the\nnetwork.\n\nThe call to get your templates is completely synchronous.\n\n**Note:** this is completely unnecessary if you use `//= require magic_lamp/all_fixtures`\n\nExample:\n```js\n// Probably should be in your `spec_helper.js`\nMagicLamp.preload();\n```\n### fixtureNames\n`MagicLamp.fixtureNames()` will return an array of all of the fixture names available in the cache\n(which is all of them if you've called [`preload`](#preload)). It will also `console.log` them out.\n\nExample\n```js\nMagicLamp.preload();\nMagicLamp.fixtureNames(); // =\u003e ['orders/foo', 'orders/bar', 'orders/baz']\n// logs 'orders/foo'\n// logs 'orders/bar'\n// logs 'orders/baz'\n```\n\n### globalize\n`MagicLamp.globalize()` will put `MagicLamp.clean` and `MagicLamp.load` onto `window` for convenience.\n\nExample:\n```js\nMagicLamp.globalize();\n\ndescribe(\"Foo\", function() {\n  beforeEach(function() {\n    load(\"orders/foo\");\n  });\n\n  afterEach(function() {\n    clean();\n  });\n\n  // ...\n});\n```\nErrors\n------\nIf there are errors rendering any of your templates, Magic Lamp will often throw a JavaScript error. Errors will also appear in your server log (if you're running the in-browser specs).\n\nTo see errors outside of the server log (which may be noisy), you can run [`rake magic_lamp:lint`](#tasks) (or `rake mll`) or visit `/magic_lamp/lint` in your browser and display any errors in your fixtures.\n\nYou can debug into your fixture generation code or even the templates themselves just as you normally would in any other part of your Rails app. If you start seeing a bunch of `RenderCatcher` objects instead of the code you expected, just continue through and wait for the debugger to catch again and things go back to normal. If you want to skip continuing through, simply provide an explicit name for the fixture.\n\nIf you get an `ActionView::MissingTemplate` error, try specifying the controller. This error is caused by a template that renders a partial\nwithout using the fully qualified path to the partial. Specifying the controller should help Rails find the template.\n\nWhen rails is inferring routes for `form_for`, `link_to`, and a few other methods you'll sometimes need to change `request.env[\"action_dispatch.request.path_parameters\"]` by setting `action` and `controller`. When the route is nested with with a parameter in the url like `/orders/:order_id/foos/new` you'll need to add the `:order_id` to it like so:\n\n```ruby\nfixture do\n  request.env[\"action_dispatch.request.path_parameters\"] = {\n    action: \"new\",\n    controller: \"foos\",\n    order_id: 3\n  }\n  render :new\nend\n```\n\nSweet aliases\n-------------\n### Ruby\n\n```ruby\nMagicLamp.register_fixture =\u003e fixture\nMagicLamp.register =\u003e fixture\nMagicLamp.rub =\u003e fixture\nMagicLamp.wish =\u003e fixture\n```\n\n### JavaScript\n```js\nMagicLamp.rub =\u003e load\nMagicLamp.wish =\u003e load\nMagicLamp.massage =\u003e preload\nMagicLamp.wishForMoreWishes =\u003e preload\nMagicLamp.polish =\u003e clean\n```\n\n### Rake Tasks\n```\nrake mlfn =\u003e rake magic_lamp:fixture_names\nrake mll =\u003e rake magic_lamp:lint\n```\n\nContributing\n------------\n1. [Fork it](https://github.com/crismali/magic_lamp/fork)\n2. Clone it locally\n3. `cd` into the project root\n4. `ruby bootstrap`\n5. `appraisal install`\n6. Run the specs with `appraisal rake`\n7. Update the `CHANGELOG.md`\n8. Create your feature branch (`git checkout -b my-new-feature`)\n9. Commit your changes (`git commit -am 'Add some feature'`)\n10. Push to the branch (`git push origin my-new-feature`)\n11. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrismali%2Fmagic_lamp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrismali%2Fmagic_lamp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrismali%2Fmagic_lamp/lists"}