diff --git a/.rspec b/.rspec index 2175b419..c62d6c14 100644 --- a/.rspec +++ b/.rspec @@ -1,5 +1,6 @@ ---color +--color --format Fuubar --format html --out coverage/rspec_results.html +--require rails_helper -r turnip/rspec diff --git a/Gemfile.lock b/Gemfile.lock index 2de21f37..4fc9ad23 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,7 +31,7 @@ GIT GIT remote: git://github.com/bterkuile/simply_stored.git - revision: aa2b456b16a14483d857404b8afe6500f8e1afb6 + revision: bf0d9f6b4645d0a24d5321b6db27bab6625c10ef branch: master specs: simply_stored (1.0.0) diff --git a/README.md b/README.md index 2d8db44a..c32ade6b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ Mozo server backend README Application architecture ----------------------------------------------- +Building the product +------------------------------------------ +1. Set the current routes to mozo-supplier client code (TODO: make way + better) +```ruby +File.write "#{ENV["MOZO_PATH_SUPPLIER"]}/app/global-functionality/js-routes.js", JsRoutes.generate.sub(/this\);\n$/, 'window);') +``` Server side monit config -------------------------------------------------- diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index b385b1b6..de01928d 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -10,3 +10,5 @@ //= link supplier/foundation1/application.css // //= link supplier/app/application.js +// +//= link qr_sheet/application.css diff --git a/app/assets/javascripts/supplier/app/application.js.coffee b/app/assets/javascripts/supplier/app/application.js.coffee index 2c56a7ae..ccc90992 100644 --- a/app/assets/javascripts/supplier/app/application.js.coffee +++ b/app/assets/javascripts/supplier/app/application.js.coffee @@ -1,18 +1,18 @@ #= require_self #= require md5 #= require handlebars -#= require ember -#= require ember-data -#= require active-model-adapter -#= require ember-validations -#= require ember-template-compiler +# require ember +# require ember-data +# require active-model-adapter +# require ember-validations +# require ember-template-compiler #= require_directory ./modifications #= require ./app -#= require shared-ember-helpers/all +# require shared-ember-helpers/all #= require_directory ./mixins #= require_directory ./services #= require ./controllers/modals/base_controller -#= require ion.sound +# require ion.sound #= require_tree . @$assets_path = '/assets/' diff --git a/app/assets/javascripts/supplier/app/modifications/component_modifications.js.coffee b/app/assets/javascripts/supplier/app/modifications/component_modifications.js.coffee index fb5e1b28..8d8da152 100644 --- a/app/assets/javascripts/supplier/app/modifications/component_modifications.js.coffee +++ b/app/assets/javascripts/supplier/app/modifications/component_modifications.js.coffee @@ -1,3 +1,4 @@ +#import Ember from 'ember' ComponentExtensions = Ember.Mixin.create modal: (name, options={})-> target = App.__container__.lookup('route:application') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c76cc4db..871ab7d4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -18,7 +18,7 @@ private def authenticate_employee! if auth_token = params[:auth_token].presence raise CanCan::AccessDenied unless employee = Employee.find_by_authentication_token(auth_token) - sign_in employee + bypass_sign_in employee else super end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index d78d9376..0c82b4e0 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -49,18 +49,23 @@ class DashboardController < ApplicationController code = "q.mozo.bar/s?t=#{@table.id}" size = RQRCode.minimum_qr_size_from_string(code) respond_to do |format| - format.html - format.svg { render qrcode: code, level: :l, unit: 10, table_number: @table.number, qcontainer: true } + format.html { + render text: "Pending table_qr_image" + } + format.svg { + render qrcode: code, level: :l, unit: 10, table_number: @table.number, qcontainer: true + } format.png do - #render qrcode: code, level: :l, table_number: @table.number, qcontainer: true - size = RQRCode.minimum_qr_size_from_string(code) - level = :l - qrcode = RQRCode::QRCode.new(code, size: size, level: level) - svg = RQRCode::Renderers::SVG::render(qrcode) - svg_file = Tempfile.new(['table_qr', '.svg']){|f| f.puts svg} - png_target = svg_file.path.sub /svg$/, 'png' + render qrcode: code, level: :l, unit: 10, table_number: @table.number, qcontainer: true + ##render qrcode: code, level: :l, table_number: @table.number, qcontainer: true + #size = RQRCode.minimum_qr_size_from_string(code) + #level = :l + #qrcode = RQRCode::QRCode.new(code, size: size, level: level) + #svg = RQRCode::Renderers::SVG::render(qrcode) + #svg_file = Tempfile.new(['table_qr', '.svg']){|f| f.puts svg} + #png_target = svg_file.path.sub /svg$/, 'png' - render nothing: true + #render nothing: true end end end diff --git a/app/controllers/suppliers/application_controller.rb b/app/controllers/suppliers/application_controller.rb index f89e202d..6ab6b692 100644 --- a/app/controllers/suppliers/application_controller.rb +++ b/app/controllers/suppliers/application_controller.rb @@ -15,17 +15,24 @@ module Suppliers rescue_from CanCan::AccessDenied do |exception| respond_to do |format| format.html { redirect_to root_path, alert: 'Action forbidden'} - format.json { render json: {errors: "403 Forbidden"}, status: :forbidden } + format.json { render json: {errors: "403 Forbidden", ok: false}, status: :forbidden } end end # GET + #NOTE: temporary solution for development, if I am in production something is wrong def employee_and_supplier employee = current_employee || Employee.find_by_email('bterkuile@gmail.com') + raise CanCan::AccessDenied unless employee.present? supplier = current_supplier || employee.suppliers.first + employee.enrich_with_settings supplier.settings_for(employee) + FlatKeys.as_nested_structure(Supplier::PRELOAD_INCLUDES).last.each do |relation_name, includes| + relation_result = supplier.public_send(relation_name) + relation_result.include_relations(includes) if relation_result.is_a?(Array) + end render json: { employee: JSONAPI::Serializer.serialize(employee, serializer: Suppliers::EmployeeSerializer), - supplier: JSONAPI::Serializer.serialize(supplier, serializer: Suppliers::SupplierSerializer), + supplier: JSONAPI::Serializer.serialize(supplier, serializer: Suppliers::SupplierSerializer, include: Supplier::PRELOAD_INCLUDES), auth_token: employee.authentication_token, } end diff --git a/app/controllers/suppliers/employee_shifts_controller.rb b/app/controllers/suppliers/employee_shifts_controller.rb index 0364499c..322bd340 100644 --- a/app/controllers/suppliers/employee_shifts_controller.rb +++ b/app/controllers/suppliers/employee_shifts_controller.rb @@ -12,18 +12,21 @@ module Suppliers render json: @employee_shifts end def create + @employee_shift = EmployeeShift.new(employee_shift_params) @employee_shift.supplier = current_supplier @employee_shift.save render json: @employee_shift end def update + @employee_shift = EmployeeShift.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @employee_shift.update employee_shift_params render json: @employee_shift end def destroy head :forbidden and return unless @employee_shift.supplier_id == current_supplier.id + @employee_shift= EmployeeShift.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @employee_shift.destroy head :no_content end diff --git a/app/controllers/suppliers/product_categories_controller.rb b/app/controllers/suppliers/product_categories_controller.rb index 9afca9b1..28f1320b 100644 --- a/app/controllers/suppliers/product_categories_controller.rb +++ b/app/controllers/suppliers/product_categories_controller.rb @@ -43,7 +43,7 @@ module Suppliers # GET /product_categories/new # GET /product_categories/new.json def new - @product_category = ProductCategory.new + @product_category = ProductCategory.new supplier: current_supplier respond_to do |format| format.html # new.html.erb diff --git a/app/controllers/suppliers/product_variants_controller.rb b/app/controllers/suppliers/product_variants_controller.rb index 58564141..17862fbd 100644 --- a/app/controllers/suppliers/product_variants_controller.rb +++ b/app/controllers/suppliers/product_variants_controller.rb @@ -53,6 +53,7 @@ module Suppliers def destroy #@product_variant = ProductVariant.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @product_variant = ProductVariant.find(params[:id]) + head :forbidden and return unless @product_variant.supplier_id == current_supplier.id @product_variant.destroy head :no_content end diff --git a/app/controllers/suppliers/products_controller.rb b/app/controllers/suppliers/products_controller.rb index bd169e93..1199693a 100644 --- a/app/controllers/suppliers/products_controller.rb +++ b/app/controllers/suppliers/products_controller.rb @@ -29,7 +29,7 @@ module Suppliers # GET /products/new # GET /products/new.json def new - @product = Product.new + @product = Product.new supplier: current_supplier @product.add_product_category ProductCategory.find_by_supplier_id_and_id!(current_supplier.id, params[:product_category_id]) if params[:product_category_id].present? respond_to do |format| @@ -46,7 +46,7 @@ module Suppliers # POST /products # POST /products.json def create - #@product = Product.new(product_params) + @product = Product.new(product_params) @product.supplier = current_supplier respond_to do |format| @@ -79,7 +79,7 @@ module Suppliers # DELETE /products/1 # DELETE /products/1.json def destroy - #@product = Product.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) + @product = Product.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @product.destroy head :no_content end diff --git a/app/controllers/suppliers/section_areas_controller.rb b/app/controllers/suppliers/section_areas_controller.rb index 520e8f31..42124567 100644 --- a/app/controllers/suppliers/section_areas_controller.rb +++ b/app/controllers/suppliers/section_areas_controller.rb @@ -6,6 +6,7 @@ module Suppliers end def create + @section_area = SectionArea.new(section_area_params) @section_area.supplier = current_supplier if @section_area.save render json: @section_area @@ -15,6 +16,7 @@ module Suppliers end def update + @section_area = SectionArea.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) if @section_area.update_attributes section_area_params render json: @section_area else @@ -23,6 +25,7 @@ module Suppliers end def destroy + @section_area= SectionArea.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @section_area.destroy head :no_content end diff --git a/app/controllers/suppliers/section_elements_controller.rb b/app/controllers/suppliers/section_elements_controller.rb index fa0ba02e..b5383797 100644 --- a/app/controllers/suppliers/section_elements_controller.rb +++ b/app/controllers/suppliers/section_elements_controller.rb @@ -6,6 +6,7 @@ module Suppliers end def create + @section_element = SectionElement.new(section_element_params) @section_element.supplier = current_supplier if @section_element.save render json: @section_element @@ -15,6 +16,7 @@ module Suppliers end def update + @section_element = SectionElement.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) if @section_element.update_attributes section_element_params render json: @section_element else @@ -23,6 +25,7 @@ module Suppliers end def destroy + @section_element= SectionElement.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @section_element.destroy head :no_content end diff --git a/app/controllers/suppliers/sections_controller.rb b/app/controllers/suppliers/sections_controller.rb index 9a5491cb..a55691d8 100644 --- a/app/controllers/suppliers/sections_controller.rb +++ b/app/controllers/suppliers/sections_controller.rb @@ -31,8 +31,7 @@ module Suppliers # GET /sections/new # GET /sections/new.json def new - @section = Section.new - @section.supplier = current_supplier + @section = Section.new supplier: current_supplier render json: @section end diff --git a/app/controllers/suppliers/suppliers_controller.rb b/app/controllers/suppliers/suppliers_controller.rb index 27c2a54e..7aedf569 100644 --- a/app/controllers/suppliers/suppliers_controller.rb +++ b/app/controllers/suppliers/suppliers_controller.rb @@ -6,7 +6,11 @@ module Suppliers end def show - current_supplier.sections.include_relations(:tables, :section_areas, :section_elements, product_categories: {products: :product_variants}) + #current_supplier.sections.include_relations(:tables, :section_areas, :section_elements, product_categories: {products: :product_variants}) + FlatKeys.as_nested_structure(Supplier::PRELOAD_INCLUDES).last.each do |relation_name, includes| + relation_result = current_supplier.public_send(relation_name) + relation_result.include_relations(includes) if relation_result.is_a?(Array) + end #render json: JSONAPI::Serializer.serialize(current_supplier, serializer: Suppliers::SupplierSerializer, include: %w[ #sections #sections.tables @@ -16,15 +20,7 @@ module Suppliers #product_categories.products #product_categories.products.product_variants #]) #.new(current_supplier).as_json - render json: current_supplier, include: %w[ - sections - sections.tables - sections.section_areas - sections.section_elements - product_categories - product_categories.products - product_categories.products.product_variants - ] + render json: current_supplier, include: Supplier::PRELOAD_INCLUDES end def update diff --git a/app/controllers/suppliers/tables_controller.rb b/app/controllers/suppliers/tables_controller.rb index d2abd3da..6f995c5b 100644 --- a/app/controllers/suppliers/tables_controller.rb +++ b/app/controllers/suppliers/tables_controller.rb @@ -12,7 +12,7 @@ module Suppliers # GET /tables/1 # GET /tables/1.json def show - @table= Table.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) + @table = Table.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) render json: @table end @@ -20,7 +20,7 @@ module Suppliers # GET /tables/new # GET /tables/new.json def new - @table = Table.new + @table = Table.new supplier: current_supplier @table.section_id = params[:section_id].presence render json: @table @@ -47,7 +47,7 @@ module Suppliers # PUT /supplier/tables/1 # PUT /supplier/tables/1.json def update - @table= Table.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) + @table = Table.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) if @table.update_attributes(table_params) render json: @table diff --git a/app/models/employee.rb b/app/models/employee.rb index 2da6657a..d0f066ab 100644 --- a/app/models/employee.rb +++ b/app/models/employee.rb @@ -10,7 +10,7 @@ class Employee DEFAULT_SETTINGS.each do |attribute, default_value| define_method(attribute) { settings.public_send attribute } define_method("#{attribute}=") do |value| - is_dirty + #is_dirty settings.set attribute, value end if default_value == true or default_value == false # boolean diff --git a/app/models/list/join_requests.rb b/app/models/list/join_requests.rb index a9e352e3..4904b348 100644 --- a/app/models/list/join_requests.rb +++ b/app/models/list/join_requests.rb @@ -17,8 +17,8 @@ class List #unless join_request_user_ids.include?(requester.id) or user_ids.include?(requester.id) # do not resend unless user_ids.include?(requester.id) # resend for the sake of it for now @join_requests = nil # bust cache + self.join_request_user_ids_will_change! self.join_request_user_ids |= [requester.id] - self.is_dirty if save broadcast_users 'user_join_request', payload: Users::JoinRequestSerializer.serialize(join_request_for_user(requester), include: %w[list user]) end @@ -31,7 +31,7 @@ class List user.active_list_id = self.id add_user(user) user.save - self.is_dirty + join_request_user_ids_will_change! save and broadcast_users 'join_request_approved', id: "jr-#{user.id}" end end @@ -39,8 +39,8 @@ class List def reject_join_request_for_user!(user_id) user_id = user_id.id if user_id.is_a?(User) # allow model to be passed as argument if join_request_user_ids.include?(user_id) + join_request_user_ids_will_change! join_request_user_ids.delete(user_id) - self.is_dirty if save # user_id is not part of the list, so should be broadcasted separately broadcast_user user_id, 'join_request_rejected', id: "jr-#{user_id}" diff --git a/app/models/section_area.rb b/app/models/section_area.rb index edd91074..b37cad02 100644 --- a/app/models/section_area.rb +++ b/app/models/section_area.rb @@ -13,6 +13,7 @@ class SectionArea view :by_supplier_id, key: :supplier_id view :by_section_id, key: :section_id + view :by_supplier_id_and_id, key: [:supplier_id, :_id] def self.for_supplier(supplier) find_all_by_supplier_id(supplier.id) diff --git a/app/models/section_element.rb b/app/models/section_element.rb index 796ce197..d2fba26d 100644 --- a/app/models/section_element.rb +++ b/app/models/section_element.rb @@ -11,6 +11,7 @@ class SectionElement view :by_supplier_id, key: :supplier_id view :by_section_id, key: :section_id + view :by_supplier_id_and_id, key: [:supplier_id, :_id] def self.for_supplier(supplier) find_all_by_supplier_id(supplier.id) diff --git a/app/models/supplier.rb b/app/models/supplier.rb index b5513796..227fdc84 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -2,6 +2,16 @@ class Supplier include SimplyStored::Couch include ActiveModel::SerializerSupport include Supplier::Counters + PRELOAD_INCLUDES = %w[ + sections + sections.tables + sections.section_areas + sections.section_elements + product_categories + product_categories.products + product_categories.products.product_variants + ] + #devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable, :confirmable diff --git a/app/services/flat_keys.rb b/app/services/flat_keys.rb new file mode 100644 index 00000000..a3216450 --- /dev/null +++ b/app/services/flat_keys.rb @@ -0,0 +1,52 @@ +# Transform a nested tructure indicated by dots to a structure as used by the ActiveRecord includes statement +# - dslams +# - ppls.distribution_cables +# => +# [:dslams, {ppls: :distribution_cables}] +class FlatKeys + class << self + + def as_nested_structure(ary) + return ary unless ary.first.is_a?(String) + nested_keys, flat_keys = ary.partition{|spec| spec['.']} + result = flat_keys.map(&:to_sym) + if nested_keys.any? + obj = {} + nested_keys.map{ |key| key.split('.').map(&:to_sym) }.each do |parts| + traverse_nest_structure(parts, obj) + end + result -= obj.keys + result.push obj + end + result + end + + def traverse_nest_structure(parts, obj) + key = parts.shift + if parts.size == 1 + case obj[key] + when nil then obj[key] = parts[0] + when Array then obj[key] |= [parts[0]] + when Hash + raise "Colliding keys for nesting of #{key} -> #{parts[0]}" unless obj[key].has_key?(parts[0]) + else # expect symbol + obj[key] = Array.wrap(obj[key]).push parts[0] unless obj[key] == parts[0] # no duplicate + end + else # parts.size > 2 + case obj[key] + when nil + obj[key] = {} + traverse_nest_structure(parts, obj[key]) + when Array + raise "Cannot traverse #{key} -> #{parts.join('.')} because existing array value #{obj[key].inspect}" + when Hash + traverse_nest_structure(parts, obj[key]) + else # expect symbol + raise "Cannot add deeper nesting for endpoing with different name #{key} -> #{obj[key]} => #{parts.join('.')}" unless obj[key] = parts[0] # same name, allows deeper nesting + obj[key] = {obj[key] => nil} # prepare for nesting + traverse_nest_structure(parts, obj[key]) + end + end + end + end +end diff --git a/app/services/supplier_employees_settings.rb b/app/services/supplier_employees_settings.rb index 753190d7..e53fc9b7 100644 --- a/app/services/supplier_employees_settings.rb +++ b/app/services/supplier_employees_settings.rb @@ -112,7 +112,7 @@ class SupplierEmployeesSettings end def persist! - all_employees_settings.supplier.is_dirty + all_employees_settings.supplier.employee_settings_storage_will_change! all_employees_settings.supplier.save end diff --git a/app/views/suppliers/tables/qr_codes.html.slim b/app/views/suppliers/tables/qr_codes.html.slim index a19c8043..fe9221aa 100644 --- a/app/views/suppliers/tables/qr_codes.html.slim +++ b/app/views/suppliers/tables/qr_codes.html.slim @@ -1,7 +1,7 @@ - if @tables.any? ul#qr-list - for table in @tables - li= image_tag(url_for(table_qr_image_path(table_id: table.id, format: :svg))) + li= image_tag(url_for(table_qr_image_path(table_id: table.id, format: params[:image_type] || 'svg'))) - else h3= t('supplier.table.add_tables_first.title') p= t('supplier.table.add_tables_first.body') diff --git a/config/application.rb b/config/application.rb index 82016203..309fb39a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -16,6 +16,13 @@ require File.expand_path('./../../lib/couchbase-setting', __FILE__) Bundler.require(*Rails.groups(assets: %w(development test user_app))) Bundler.require(:assets) if ENV['DEPLOY']=='yes' +class CouchRest::Connection + alias_method :old_execute, :execute + def execute(method, path, options, payload = nil, &block) + Rails.logger.debug "Couch: #{method} #{Rack::Utils.unescape path} #{options}" + old_execute(method, path, options, payload, &block) + end +end # Bug in actionview error handling, remove for versions > 6.0.2.1 module ActionView # = Action View Errors @@ -291,7 +298,7 @@ module Qwaiter allow do origins '*' #resource '/user/*', :headers => '*', :methods => '*' #[:get, :post, :options] - resource '*', headers: :any, methods: '*' #[:get, :post, :options] + resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options] end end diff --git a/config/environments/test.rb b/config/environments/test.rb index 73b23b0c..7b143266 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -19,7 +19,7 @@ Qwaiter::Application.configure do config.static_cache_control = "public, max-age=3600" config.assets.compress = false - config.ember.variant = :development + #config.ember.variant = :development # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/lib/rqrcode-rails3.rb b/lib/rqrcode-rails3.rb index 9180b1e0..a30c8598 100644 --- a/lib/rqrcode-rails3.rb +++ b/lib/rqrcode-rails3.rb @@ -3,10 +3,10 @@ require 'rqrcode' require 'rqrcode-rails3/size_calculator.rb' require 'rqrcode-rails3/renderers/svg.rb' -module RQRCode - Mime::Type.register "image/svg+xml", :svg unless Mime::Type.lookup_by_extension(:svg) - Mime::Type.register "image/png", :png unless Mime::Type.lookup_by_extension(:png) +Mime::Type.register "image/svg+xml", :svg unless Mime::Type.lookup_by_extension(:svg) +Mime::Type.register "image/png", :png unless Mime::Type.lookup_by_extension(:png) +module RQRCode extend SizeCalculator ActionController::Renderers.add :qrcode do |string, options| @@ -14,11 +14,10 @@ module RQRCode size = options[:size] || RQRCode.minimum_qr_size_from_string(string) level = options[:level] || :h - qrcode = RQRCode::QRCode.new(string, :size => size, :level => level) + qrcode = RQRCode::QRCode.new(string, size: size, level: level) svg = RQRCode::Renderers::SVG::render(qrcode, options) - data = \ - if format == :png + data = if format == :png image = MiniMagick::Image.read(svg) { |i| i.format "svg" } image.format "png" png = image.to_blob @@ -26,6 +25,7 @@ module RQRCode svg end - self.response_body = render_to_string(:text => data, :template => nil) + #self.response_body = render_to_string(text: data, template: nil) + send_data data, type: content_type end end diff --git a/lib/rqrcode-rails3/renderers/svg.rb b/lib/rqrcode-rails3/renderers/svg.rb index 55a51b9c..993529f0 100644 --- a/lib/rqrcode-rails3/renderers/svg.rb +++ b/lib/rqrcode-rails3/renderers/svg.rb @@ -15,29 +15,29 @@ module RQRCode unit = options[:unit] || 11 # height and width dependent on offset and QR complexity - dimension = (qrcode.module_count*unit) + (2*offset) + dimension = (qrcode.modules.count*unit) + (2*offset) xml_tag = %{} open_tag = %{} close_tag = "" result = [] - for c in 0...qrcode.module_count + for c in 0...qrcode.modules.count tmp = [] - for r in 0...qrcode.module_count + for r in 0...qrcode.modules.count y = c*unit + offset x = r*unit + offset - next unless qrcode.dark?(c, r) + next unless qrcode.qrcode.checked?(c, r) tmp << %{} - end + end result << tmp.join("\n") end - + if options[:fill] result.unshift %{} end - + return [xml_tag, open_tag, result, close_tag].flatten.join("\n") unless options[:qcontainer] svg = File.read(File.expand_path('../../qr_container.svg', __FILE__)) svg.gsub!(/#table_number/, options[:table_number].to_s) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 00000000..bd57557b --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,221 @@ +require 'spec_helper' + +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../config/environment", File.dirname(__FILE__)) +require 'rspec/rails' +require 'rspec/matchers' +require 'capybara/rspec' +require 'turnip/capybara' +require 'in_memory_q_counter' +require 'capybara-screenshot/rspec' +require 'webmock/rspec' +require 'capybara/poltergeist' + +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} +#Dir[Rails.root.join("spec/factories/**/*.rb")].each {|f| require f } +Dir.glob("spec/acceptance_steps/**/*steps.rb") { |f| load f, true } + +I18n.locale =I18n.default_locale +Devise.stretches = 1 +#Capybara.javascript_driver = :webkit +Capybara.javascript_driver = :poltergeist +#Capybara.javascript_driver = :selenium +Capybara.default_max_wait_time = 5 # ember needs more time than the default of 2 +Capybara.server_port = 62625 +Capybara::Screenshot.webkit_options = { width: 1024, height: 768 } +WebMock.disable_net_connect!(allow_localhost: true) + +class Ability + include CanCan::Ability + def initialize(record) + can :manage, :all + end +end +module TurnipHacks + def run_step(*) + # delay for a nice follow in selenium + #sleep 0.6 + super + end +end + +module FactoryAttributesFor + def attributes_for(obj, options={}) + super(obj, options).merge(build(obj).attributes.select{|k,v| k =~ /_id$/}).symbolize_keys + end +end + +module RequestSpecHelpers + module MethodsForHash + def method_missing(m, *args) + r = self[m.to_s.dasherize] + if r.is_a?(Hash) + r.extend MethodsForHash + end + r + end + end + def api_response + result = JSON.parse(response.body) + result.extend MethodsForHash + #result.extend Hashie::Extensions::DeepFind + result + end +end + +module SpecSelectorHelpers + def top_navigation + '.navbar-fixed-top' + end + + # Uses the click_on method for capybara + def click_on_translation(key) + text = I18n.t(key) + text.should_not =~ /missing/ + click_on text + end + + # same as save_and_open_page but with styling + def show_page + save_page Rails.root.join( 'public', 'capybara.html' ) + %x(launchy http://localhost:3000/capybara.html) + end + +end + +class TestCounter < InMemoryQCounter + #def incr(*args) + #result = super + #puts "Counter incr called with #{args.inspect} giving result #{result}" + #result + #end +end + +# No external images in test suite... slow.... +User.send(:define_method, :avatar, ->{}) + + +if defined?(Couchbase) + class Couchbase::View + alias :old_initialize :initialize + def initialize(bucket, endpoint, params = {}) + old_initialize(bucket, endpoint, params.merge(stale: false)) + end + end +end + +RSpec.configure do |config| + # == Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + #config.mock_with :rspec + config.include FactoryGirl::Syntax::Methods + config.include FactoryAttributesFor + config.include Devise::TestHelpers, type: :controller + config.include SpecControllerHelpers, type: :controller + config.include EndWithMatcher + config.include Matchers + config.include TurnipHacks, turnip: true + config.include ActiveSupport::Testing::TimeHelpers + config.include Features::BasicHelpers, type: :feature + config.include SpecRouteHelpers, type: :feature + config.include SpecEmberHelpers, type: :feature + config.include SerializersTestHelpers, type: :serializer + config.include Warden::Test::Helpers, type: :request + config.include RequestSpecHelpers, type: :request + #config.use_transactional_fixtures = true + config.infer_base_class_for_anonymous_controllers = true + config.filter_run_excluding broken: true + config.render_views = true + config.expect_with(:rspec) { |c| c.syntax = [:expect, :should] } + + OmniAuth.config.test_mode = true + OmniAuth.config.add_mock :facebook, { + info: { + nickname: 'Joey', + name: "Facebook Joe", + first_name: "Facebook Joe" + }, + credentials: { + 'token' => 'fbAuthToken234', + 'expires_at' => 1.week.from_now.to_i, + 'expires' => true + }, + uid: '123456790' + } + + OmniAuth.config.add_mock :instagram, { + info: { + nickname: 'Iggy', + name: "Instagram Jane", + first_name: "Insta" + }, + credentials: { + 'token' => 'igAuthToken234', + 'expires_at' => 1.week.from_now.to_i, + 'expires' => true + }, + uid: '123498765' + } + + # Use color in STDOUT + config.color = true + config.fail_fast = false + + # Use color not only in STDOUT but also in pagers and files + config.tty = true + + # Use the specified formatter + #config.formatter = :documentation # :progress, :html, :textmate + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + #config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + #config.use_transactional_fixtures = true + config.before :suite do + Qwaiter::Couchbase.load_design_docs! + Qwaiter::Counter.connection = TestCounter.new + end + + config.before :each do + CouchPotato.couchrest_database.recreate! + Qwaiter::Counter.connection.flush + end + + config.before :each, type: :feature do + #Supplier.any_instance.stub send_confirmation_instructions: true + Capybara.session_name = :default + end + + config.around :each, type: :request do |example| + Warden.test_mode! + example.run + Warden.test_reset! + end + + + config.after :suite do +=begin + rspec_outfile = Rails.root.join('coverage/rspec_results.html') + result = File.read rspec_outfile + replacement = %|
Coverage
| + result.gsub! //, replacement + File.open(rspec_outfile, 'w'){|f| f.puts result} + `open #{rspec_outfile}` +=end + end + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + #config.infer_base_class_for_anonymous_controllers = true +end diff --git a/spec/services/flat_keys_spec.rb b/spec/services/flat_keys_spec.rb new file mode 100644 index 00000000..6ce64a0e --- /dev/null +++ b/spec/services/flat_keys_spec.rb @@ -0,0 +1,73 @@ +RSpec.describe FlatKeys do + describe '#as_nested_structure' do + it "works" do + result = FlatKeys.as_nested_structure([ + 'root_one', + 'inventories.location.site', + 'ppls.distribution_cables', + 'dslams.port_spec', + 'root_two', + 'dslams.other_spec', + 'root_three', + #'dslams.other_spec.and_then.some', # should raise + 'very.deep.nested.structure.just.because.we.can', + 'very.deep.nested.structure.with.other.tail', + 'start.with.more.than.what.comes.after', + 'start.with.more.than.what.comes', + 'start.with.less.than.what.comes', + 'start.with.less.than.what.comes2.after', + 'start.with.less.than.what.comes.after', + 'start.with.less.than.what.comes2.after', # duplicate, should be no problem + ]) + + expect( result ).to eq [ + :root_one, + :root_two, + :root_three, + { + inventories: {location: :site}, + ppls: :distribution_cables, + dslams: [:port_spec, :other_spec], + very: { + deep: { + nested: { + structure: { + just: { + because: {we: :can} + }, + with: {other: :tail} + } + } + } + }, + start: { + with: { + more: { + than: {what: {comes: :after}} + }, + less: { + than: {what: {comes: :after, comes2: :after}} + } + } + } + } + ] + end + + it "removes root duplicates" do + result = FlatKeys.as_nested_structure(%w[ + sections + sections.tables + sections.section_areas + sections.section_elements + product_categories + product_categories.products + product_categories.products.product_variants + ]) + expect( result ).to eq [{ + product_categories: {products: :product_variants}, + sections: [:tables, :section_areas, :section_elements] + }] + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 96b2bb26..9ab9c9eb 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,223 +1,5 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' #require 'simplecov' #SimpleCov.start 'rails' -ENV["RAILS_ENV"] ||= 'test' -require File.expand_path("../config/environment", File.dirname(__FILE__)) -require 'rspec/rails' -require 'rspec/matchers' -require 'capybara/rspec' -require 'turnip/capybara' -require 'in_memory_q_counter' -require 'capybara-screenshot/rspec' -require 'webmock/rspec' -require 'capybara/poltergeist' - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} -#Dir[Rails.root.join("spec/factories/**/*.rb")].each {|f| require f } -Dir.glob("spec/acceptance_steps/**/*steps.rb") { |f| load f, true } - -I18n.locale =I18n.default_locale -Devise.stretches = 1 -#Capybara.javascript_driver = :webkit -Capybara.javascript_driver = :poltergeist -#Capybara.javascript_driver = :selenium -Capybara.default_max_wait_time = 5 # ember needs more time than the default of 2 -Capybara.server_port = 62625 -Capybara::Screenshot.webkit_options = { width: 1024, height: 768 } -WebMock.disable_net_connect!(allow_localhost: true) #Capybara.javascript_driver = :selenium -module TurnipHacks - def run_step(*) - # delay for a nice follow in selenium - #sleep 0.6 - super - end -end - -module FactoryAttributesFor - def attributes_for(obj, options={}) - super(obj, options).merge(build(obj).attributes.select{|k,v| k =~ /_id$/}).symbolize_keys - end -end - -module RequestSpecHelpers - module MethodsForHash - def method_missing(m, *args) - r = self[m.to_s.dasherize] - if r.is_a?(Hash) - r.extend MethodsForHash - end - r - end - end - def api_response - result = JSON.parse(response.body) - result.extend MethodsForHash - #result.extend Hashie::Extensions::DeepFind - result - end -end - -module SpecSelectorHelpers - def top_navigation - '.navbar-fixed-top' - end - - # Uses the click_on method for capybara - def click_on_translation(key) - text = I18n.t(key) - text.should_not =~ /missing/ - click_on text - end - - # same as save_and_open_page but with styling - def show_page - save_page Rails.root.join( 'public', 'capybara.html' ) - %x(launchy http://localhost:3000/capybara.html) - end - -end - -class Ability - include CanCan::Ability - def initialize(record) - can :manage, :All - end -end -class TestCounter < InMemoryQCounter - #def incr(*args) - #result = super - #puts "Counter incr called with #{args.inspect} giving result #{result}" - #result - #end -end - -# No external images in test suite... slow.... -User.send(:define_method, :avatar, ->{}) - - -if defined?(Couchbase) - class Couchbase::View - alias :old_initialize :initialize - def initialize(bucket, endpoint, params = {}) - old_initialize(bucket, endpoint, params.merge(stale: false)) - end - end -end - -RSpec.configure do |config| - # == Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - #config.mock_with :rspec - config.include FactoryGirl::Syntax::Methods - config.include FactoryAttributesFor - config.include Devise::TestHelpers, type: :controller - config.include SpecControllerHelpers, type: :controller - config.include EndWithMatcher - config.include Matchers - config.include TurnipHacks, turnip: true - config.include ActiveSupport::Testing::TimeHelpers - config.include Features::BasicHelpers, type: :feature - config.include SpecRouteHelpers, type: :feature - config.include SpecEmberHelpers, type: :feature - config.include SerializersTestHelpers, type: :serializer - config.include Warden::Test::Helpers, type: :request - config.include RequestSpecHelpers, type: :request - #config.use_transactional_fixtures = true - config.infer_base_class_for_anonymous_controllers = true - config.filter_run_excluding broken: true - config.render_views = true - config.expect_with(:rspec) { |c| c.syntax = [:expect, :should] } - - OmniAuth.config.test_mode = true - OmniAuth.config.add_mock :facebook, { - info: { - nickname: 'Joey', - name: "Facebook Joe", - first_name: "Facebook Joe" - }, - credentials: { - 'token' => 'fbAuthToken234', - 'expires_at' => 1.week.from_now.to_i, - 'expires' => true - }, - uid: '123456790' - } - - OmniAuth.config.add_mock :instagram, { - info: { - nickname: 'Iggy', - name: "Instagram Jane", - first_name: "Insta" - }, - credentials: { - 'token' => 'igAuthToken234', - 'expires_at' => 1.week.from_now.to_i, - 'expires' => true - }, - uid: '123498765' - } - - # Use color in STDOUT - config.color = true - config.fail_fast = false - - # Use color not only in STDOUT but also in pagers and files - config.tty = true - - # Use the specified formatter - #config.formatter = :documentation # :progress, :html, :textmate - - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - #config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - #config.use_transactional_fixtures = true - config.before :suite do - Qwaiter::Couchbase.load_design_docs! - Qwaiter::Counter.connection = TestCounter.new - end - - config.before :each do - CouchPotato.couchrest_database.recreate! - Qwaiter::Counter.connection.flush - end - - config.before :each, type: :feature do - #Supplier.any_instance.stub send_confirmation_instructions: true - Capybara.session_name = :default - end - - config.around :each, type: :request do |example| - Warden.test_mode! - example.run - Warden.test_reset! - end - - - config.after :suite do -=begin - rspec_outfile = Rails.root.join('coverage/rspec_results.html') - result = File.read rspec_outfile - replacement = %|
Coverage
| - result.gsub! //, replacement - File.open(rspec_outfile, 'w'){|f| f.puts result} - `open #{rspec_outfile}` -=end - end - - # If true, the base class of anonymous controllers will be inferred - # automatically. This will be the default behavior in future versions of - # rspec-rails. - #config.infer_base_class_for_anonymous_controllers = true -end