spontaneous 0.1.0.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +49 -0
- data/Gemfile.lock +146 -0
- data/LICENSE +0 -0
- data/README +0 -0
- data/Rakefile +284 -0
- data/Readme.markdown +7 -0
- data/application/css/add_alias_dialogue.scss +27 -0
- data/application/css/definitions.scss +249 -0
- data/application/css/developer.scss +9 -0
- data/application/css/editing.scss +649 -0
- data/application/css/login.scss +91 -0
- data/application/css/min/54ee0ed3c7fac7632bd5c020d69e9a2503e0c88c.css +1 -0
- data/application/css/min/c256adc144e2bdd0b0539356b04eb62db01e1dc3.css +1 -0
- data/application/css/popover.scss +335 -0
- data/application/css/schema_error.scss +90 -0
- data/application/css/spontaneous.scss +111 -0
- data/application/css/unsupported.scss +16 -0
- data/application/css/v2.scss +1606 -0
- data/application/css/variables.scss +80 -0
- data/application/js/add_alias_dialogue.js +59 -0
- data/application/js/add_home_dialogue.js +59 -0
- data/application/js/ajax.js +99 -0
- data/application/js/authentication.js +22 -0
- data/application/js/box.js +104 -0
- data/application/js/box_container.js +82 -0
- data/application/js/compatibility.js +132 -0
- data/application/js/conflicted_field_dialogue.js +92 -0
- data/application/js/content.js +224 -0
- data/application/js/content_area.js +44 -0
- data/application/js/dialogue.js +196 -0
- data/application/js/dom.js +71 -0
- data/application/js/edit_dialogue.js +137 -0
- data/application/js/edit_panel.js +232 -0
- data/application/js/editing.js +42 -0
- data/application/js/entry.js +13 -0
- data/application/js/extensions.js +104 -0
- data/application/js/field.js +4 -0
- data/application/js/field_preview.js +55 -0
- data/application/js/field_types/date_field.js +16 -0
- data/application/js/field_types/file_field.js +71 -0
- data/application/js/field_types/image_field.js +358 -0
- data/application/js/field_types/markdown_field.js +656 -0
- data/application/js/field_types/string_field.js +185 -0
- data/application/js/image.js +72 -0
- data/application/js/init.js +34 -0
- data/application/js/load.js +4 -0
- data/application/js/location.js +157 -0
- data/application/js/login.js +53 -0
- data/application/js/min/492a209de8ee955fa9c729a765377495001e11b1.js +17 -0
- data/application/js/min/80f684d77c940887a1d4a63e3a96102e993baa98.js +88 -0
- data/application/js/min/b8abf302a824c35385ff517b34111e1710ff3b37.js +2 -0
- data/application/js/min/c7140ec9475e5bf868b901e0621338d7d162358b.js +3 -0
- data/application/js/min/f07f2bd6630ee31e1c2288ec223383d8f0658ba6.js +2 -0
- data/application/js/page.js +43 -0
- data/application/js/page_browser.js +147 -0
- data/application/js/page_entry.js +47 -0
- data/application/js/popover.js +99 -0
- data/application/js/popover_view.js +56 -0
- data/application/js/preview.js +64 -0
- data/application/js/progress.js +358 -0
- data/application/js/properties.js +90 -0
- data/application/js/publish.js +187 -0
- data/application/js/require.js +129 -0
- data/application/js/sharded_upload.js +206 -0
- data/application/js/side_bar.js +30 -0
- data/application/js/spontaneous.js +6 -0
- data/application/js/state.js +64 -0
- data/application/js/status_bar.js +47 -0
- data/application/js/top_bar.js +368 -0
- data/application/js/types.js +98 -0
- data/application/js/upload.js +88 -0
- data/application/js/upload_manager.js +319 -0
- data/application/js/user.js +37 -0
- data/application/js/vendor/.DS_Store +0 -0
- data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +283 -0
- data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +30 -0
- data/application/js/vendor/JS.Class-2.1.5/README +30 -0
- data/application/js/vendor/JS.Class-2.1.5/min/command.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/core.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/hash.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/loader.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/observable.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/package.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/set.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/state.js +1 -0
- data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +16 -0
- data/application/js/vendor/JS.Class-2.1.5/src/command.js +93 -0
- data/application/js/vendor/JS.Class-2.1.5/src/comparable.js +37 -0
- data/application/js/vendor/JS.Class-2.1.5/src/constant_scope.js +48 -0
- data/application/js/vendor/JS.Class-2.1.5/src/core.js +1060 -0
- data/application/js/vendor/JS.Class-2.1.5/src/decorator.js +50 -0
- data/application/js/vendor/JS.Class-2.1.5/src/enumerable.js +505 -0
- data/application/js/vendor/JS.Class-2.1.5/src/forwardable.js +22 -0
- data/application/js/vendor/JS.Class-2.1.5/src/hash.js +334 -0
- data/application/js/vendor/JS.Class-2.1.5/src/linked_list.js +114 -0
- data/application/js/vendor/JS.Class-2.1.5/src/loader.js +553 -0
- data/application/js/vendor/JS.Class-2.1.5/src/method_chain.js +172 -0
- data/application/js/vendor/JS.Class-2.1.5/src/observable.js +55 -0
- data/application/js/vendor/JS.Class-2.1.5/src/package.js +472 -0
- data/application/js/vendor/JS.Class-2.1.5/src/proxy.js +58 -0
- data/application/js/vendor/JS.Class-2.1.5/src/ruby.js +44 -0
- data/application/js/vendor/JS.Class-2.1.5/src/set.js +332 -0
- data/application/js/vendor/JS.Class-2.1.5/src/stack_trace.js +151 -0
- data/application/js/vendor/JS.Class-2.1.5/src/state.js +95 -0
- data/application/js/vendor/JS.Class-2.1.5/src/stdlib.js +2612 -0
- data/application/js/vendor/crypto-2.3.0-crypto.js +160 -0
- data/application/js/vendor/crypto-2.3.0-sha1.js +91 -0
- data/application/js/vendor/diff_match_patch.js +2153 -0
- data/application/js/vendor/jquery-1.4.2.min.js +154 -0
- data/application/js/vendor/jquery-1.4.3.min.js +166 -0
- data/application/js/vendor/jquery-1.5.1.min.js +16 -0
- data/application/js/vendor/jquery-1.5.1rc1.min.js +24 -0
- data/application/js/vendor/jquery-1.6.2.min.js +18 -0
- data/application/js/vendor/jquery-ui-1.8.6.custom.min.js +265 -0
- data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +415 -0
- data/application/js/vendor/jquery-ui-1.8.custom.min.js +106 -0
- data/application/js/vendor/jquery.hotkeys-0.7.9.js +248 -0
- data/application/js/vendor/jquery.hotkeys-0.7.9.min.js +19 -0
- data/application/js/vendor/jsdiff.js +169 -0
- data/application/js/views/box_view.js +229 -0
- data/application/js/views/page_piece_view.js +45 -0
- data/application/js/views/page_view.js +238 -0
- data/application/js/views/piece_view.js +178 -0
- data/application/js/views.js +110 -0
- data/application/static/editing-0-noise.png +0 -0
- data/application/static/editing-1-noise.png +0 -0
- data/application/static/editing-texture-1.png +0 -0
- data/application/static/editing-texture.png +0 -0
- data/application/static/editing-toolbar-shadow-bottom.png +0 -0
- data/application/static/editing-toolbar-shadow-top.png +0 -0
- data/application/static/favicon.ico +0 -0
- data/application/static/inner-glow.png +0 -0
- data/application/static/item-buttons.png +0 -0
- data/application/static/location-arrow.png +0 -0
- data/application/static/logo-400px-transparent.png +0 -0
- data/application/static/missing.png +0 -0
- data/application/static/orange-down-arrow.png +0 -0
- data/application/static/page-browser-next.png +0 -0
- data/application/static/paper-texture-dark.png +0 -0
- data/application/static/px.gif +0 -0
- data/application/static/select-arrow-root.png +0 -0
- data/application/static/select-arrow.png +0 -0
- data/application/static/slot-down-arrow.png +0 -0
- data/application/static/splash.png +0 -0
- data/application/static/spontaneous.png +0 -0
- data/application/static/spot.png +0 -0
- data/application/static/spot.svg +40 -0
- data/application/static/texture.png +0 -0
- data/application/views/index.erubis +46 -0
- data/application/views/login.erubis +69 -0
- data/application/views/schema_modification_error.html.erb +61 -0
- data/application/views/unsupported.erubis +23 -0
- data/bin/limit-upload +5 -0
- data/bin/spot +10 -0
- data/bin/unlimit-upload +3 -0
- data/config/nginx.conf +60 -0
- data/db/migrations/20100610142136_init.rb +66 -0
- data/db/migrations/20101130104334_timestamps.rb +44 -0
- data/db/migrations/20101202113205_site_publishing_flags.rb +12 -0
- data/db/migrations/20101206124543_aliases.rb +16 -0
- data/db/migrations/20110201133550_visibility.rb +27 -0
- data/db/migrations/20110209152710_users_and_groups.rb +58 -0
- data/db/migrations/20110215133910_boxes.rb +25 -0
- data/db/migrations/20110521114145_remove_slots_and_entries.rb +21 -0
- data/db/migrations/20110604192145_rename_schema_id_columns.rb +22 -0
- data/db/migrations/20110805141925_rename_site_to_state.rb +11 -0
- data/lib/cutaneous/context_helper.rb +82 -0
- data/lib/cutaneous/first_pass_parser.rb +23 -0
- data/lib/cutaneous/first_pass_renderer.rb +18 -0
- data/lib/cutaneous/parser_core.rb +18 -0
- data/lib/cutaneous/preview_context.rb +31 -0
- data/lib/cutaneous/preview_renderer.rb +15 -0
- data/lib/cutaneous/publish_context.rb +9 -0
- data/lib/cutaneous/renderer.rb +122 -0
- data/lib/cutaneous/request_context.rb +8 -0
- data/lib/cutaneous/second_pass_parser.rb +23 -0
- data/lib/cutaneous/second_pass_renderer.rb +18 -0
- data/lib/cutaneous.rb +47 -0
- data/lib/sequel/plugins/content_table_inheritance.rb +196 -0
- data/lib/sequel/plugins/yajl_serialization.rb +154 -0
- data/lib/spontaneous/application/feature.rb +9 -0
- data/lib/spontaneous/application/plugin.rb +13 -0
- data/lib/spontaneous/application.rb +8 -0
- data/lib/spontaneous/box.rb +232 -0
- data/lib/spontaneous/box_style.rb +64 -0
- data/lib/spontaneous/change.rb +107 -0
- data/lib/spontaneous/cli/adapter.rb +13 -0
- data/lib/spontaneous/cli/base.rb +184 -0
- data/lib/spontaneous/cli/console.rb +0 -0
- data/lib/spontaneous/cli/media.rb +13 -0
- data/lib/spontaneous/cli/server.rb +50 -0
- data/lib/spontaneous/cli/site.rb +46 -0
- data/lib/spontaneous/cli/sync.rb +42 -0
- data/lib/spontaneous/cli/tasks.rb +9 -0
- data/lib/spontaneous/cli.rb +83 -0
- data/lib/spontaneous/collections/box_set.rb +56 -0
- data/lib/spontaneous/collections/change_set.rb +43 -0
- data/lib/spontaneous/collections/entry_set.rb +83 -0
- data/lib/spontaneous/collections/field_set.rb +53 -0
- data/lib/spontaneous/collections/prototype_set.rb +131 -0
- data/lib/spontaneous/collections/style_set.rb +13 -0
- data/lib/spontaneous/config.rb +156 -0
- data/lib/spontaneous/constants.rb +24 -0
- data/lib/spontaneous/content.rb +113 -0
- data/lib/spontaneous/content_query.rb +17 -0
- data/lib/spontaneous/errors.rb +48 -0
- data/lib/spontaneous/extensions/array.rb +18 -0
- data/lib/spontaneous/extensions/class.rb +17 -0
- data/lib/spontaneous/extensions/hash.rb +18 -0
- data/lib/spontaneous/extensions/json.rb +26 -0
- data/lib/spontaneous/extensions/kernel.rb +7 -0
- data/lib/spontaneous/extensions/object.rb +30 -0
- data/lib/spontaneous/extensions/object_space.rb +12 -0
- data/lib/spontaneous/extensions/string.rb +44 -0
- data/lib/spontaneous/facet.rb +47 -0
- data/lib/spontaneous/field_types/date_field.rb +12 -0
- data/lib/spontaneous/field_types/field.rb +252 -0
- data/lib/spontaneous/field_types/image_field.rb +329 -0
- data/lib/spontaneous/field_types/markdown_field.rb +37 -0
- data/lib/spontaneous/field_types/string_field.rb +14 -0
- data/lib/spontaneous/field_types.rb +40 -0
- data/lib/spontaneous/generators/page/inline.html.cut +1 -0
- data/lib/spontaneous/generators/page/page.html.cut.tt +4 -0
- data/lib/spontaneous/generators/page/page.rb.tt +9 -0
- data/lib/spontaneous/generators/page.rb +38 -0
- data/lib/spontaneous/generators/site/.gitignore +4 -0
- data/lib/spontaneous/generators/site/Gemfile.tt +31 -0
- data/lib/spontaneous/generators/site/Rakefile.tt +6 -0
- data/lib/spontaneous/generators/site/config/back.ru +7 -0
- data/lib/spontaneous/generators/site/config/boot.rb +19 -0
- data/lib/spontaneous/generators/site/config/database.yml.tt +21 -0
- data/lib/spontaneous/generators/site/config/deploy.rb.tt +0 -0
- data/lib/spontaneous/generators/site/config/environment.rb.tt +8 -0
- data/lib/spontaneous/generators/site/config/environments/development.rb.tt +15 -0
- data/lib/spontaneous/generators/site/config/environments/production.rb.tt +5 -0
- data/lib/spontaneous/generators/site/config/front.ru +8 -0
- data/lib/spontaneous/generators/site/config/user_levels.yml +22 -0
- data/lib/spontaneous/generators/site/lib/site.rb.tt +4 -0
- data/lib/spontaneous/generators/site/lib/tasks/site.rake.tt +8 -0
- data/lib/spontaneous/generators/site/public/css/site.css +0 -0
- data/lib/spontaneous/generators/site/public/favicon.ico +0 -0
- data/lib/spontaneous/generators/site/public/js/.empty_directory +0 -0
- data/lib/spontaneous/generators/site/public/js/site.js +0 -0
- data/lib/spontaneous/generators/site/public/robots.txt +0 -0
- data/lib/spontaneous/generators/site/schema/.map +1 -0
- data/lib/spontaneous/generators/site/schema/page.rb.tt +8 -0
- data/lib/spontaneous/generators/site/schema/piece.rb.tt +4 -0
- data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +13 -0
- data/lib/spontaneous/generators/site.rb +77 -0
- data/lib/spontaneous/generators.rb +23 -0
- data/lib/spontaneous/image_size.rb +117 -0
- data/lib/spontaneous/json.rb +33 -0
- data/lib/spontaneous/layout.rb +15 -0
- data/lib/spontaneous/loader.rb +280 -0
- data/lib/spontaneous/logger.rb +369 -0
- data/lib/spontaneous/media.rb +84 -0
- data/lib/spontaneous/page.rb +92 -0
- data/lib/spontaneous/page_controller.rb +18 -0
- data/lib/spontaneous/page_piece.rb +77 -0
- data/lib/spontaneous/paths.rb +30 -0
- data/lib/spontaneous/permissions/access_group.rb +50 -0
- data/lib/spontaneous/permissions/access_key.rb +35 -0
- data/lib/spontaneous/permissions/user.rb +167 -0
- data/lib/spontaneous/permissions/user_level.rb +177 -0
- data/lib/spontaneous/permissions.rb +55 -0
- data/lib/spontaneous/piece.rb +30 -0
- data/lib/spontaneous/plugins/aliases.rb +128 -0
- data/lib/spontaneous/plugins/allowed_types.rb +173 -0
- data/lib/spontaneous/plugins/application/facets.rb +25 -0
- data/lib/spontaneous/plugins/application/paths.rb +137 -0
- data/lib/spontaneous/plugins/application/render.rb +29 -0
- data/lib/spontaneous/plugins/application/serialisation.rb +16 -0
- data/lib/spontaneous/plugins/application/state.rb +86 -0
- data/lib/spontaneous/plugins/boxes.rb +84 -0
- data/lib/spontaneous/plugins/controllers.rb +52 -0
- data/lib/spontaneous/plugins/entries.rb +193 -0
- data/lib/spontaneous/plugins/entry.rb +51 -0
- data/lib/spontaneous/plugins/fields.rb +103 -0
- data/lib/spontaneous/plugins/instance_code.rb +18 -0
- data/lib/spontaneous/plugins/layouts.rb +87 -0
- data/lib/spontaneous/plugins/media.rb +41 -0
- data/lib/spontaneous/plugins/page/formats.rb +67 -0
- data/lib/spontaneous/plugins/page/request.rb +89 -0
- data/lib/spontaneous/plugins/page_search.rb +64 -0
- data/lib/spontaneous/plugins/page_tree.rb +25 -0
- data/lib/spontaneous/plugins/paths.rb +125 -0
- data/lib/spontaneous/plugins/permissions.rb +63 -0
- data/lib/spontaneous/plugins/prototypes.rb +84 -0
- data/lib/spontaneous/plugins/publishing.rb +255 -0
- data/lib/spontaneous/plugins/render.rb +24 -0
- data/lib/spontaneous/plugins/schema_hierarchy.rb +76 -0
- data/lib/spontaneous/plugins/schema_id.rb +60 -0
- data/lib/spontaneous/plugins/schema_title.rb +33 -0
- data/lib/spontaneous/plugins/serialisation.rb +67 -0
- data/lib/spontaneous/plugins/site/instance.rb +22 -0
- data/lib/spontaneous/plugins/site/map.rb +19 -0
- data/lib/spontaneous/plugins/site/publishing.rb +74 -0
- data/lib/spontaneous/plugins/site/revisions.rb +28 -0
- data/lib/spontaneous/plugins/site/selectors.rb +41 -0
- data/lib/spontaneous/plugins/site_map.rb +34 -0
- data/lib/spontaneous/plugins/styles.rb +119 -0
- data/lib/spontaneous/plugins/supertype.rb +11 -0
- data/lib/spontaneous/plugins/visibility.rb +151 -0
- data/lib/spontaneous/plugins.rb +20 -0
- data/lib/spontaneous/prototypes/box_prototype.rb +168 -0
- data/lib/spontaneous/prototypes/field_prototype.rb +112 -0
- data/lib/spontaneous/prototypes/layout_prototype.rb +17 -0
- data/lib/spontaneous/prototypes/style_prototype.rb +42 -0
- data/lib/spontaneous/proxy_object.rb +12 -0
- data/lib/spontaneous/publishing/fire_and_forget.rb +57 -0
- data/lib/spontaneous/publishing/immediate.rb +197 -0
- data/lib/spontaneous/publishing/threaded.rb +25 -0
- data/lib/spontaneous/publishing.rb +10 -0
- data/lib/spontaneous/rack/around_back.rb +44 -0
- data/lib/spontaneous/rack/around_front.rb +29 -0
- data/lib/spontaneous/rack/around_preview.rb +26 -0
- data/lib/spontaneous/rack/assets.rb +98 -0
- data/lib/spontaneous/rack/back.rb +729 -0
- data/lib/spontaneous/rack/front.rb +41 -0
- data/lib/spontaneous/rack/http.rb +18 -0
- data/lib/spontaneous/rack/media.rb +29 -0
- data/lib/spontaneous/rack/public.rb +232 -0
- data/lib/spontaneous/rack/reloader.rb +42 -0
- data/lib/spontaneous/rack/static.rb +25 -0
- data/lib/spontaneous/rack.rb +55 -0
- data/lib/spontaneous/render/context.rb +100 -0
- data/lib/spontaneous/render/development_renderer.rb +14 -0
- data/lib/spontaneous/render/engine.rb +19 -0
- data/lib/spontaneous/render/format/html.rb +5 -0
- data/lib/spontaneous/render/format.rb +70 -0
- data/lib/spontaneous/render/preview_renderer.rb +18 -0
- data/lib/spontaneous/render/published_renderer.rb +54 -0
- data/lib/spontaneous/render/publishing_renderer.rb +13 -0
- data/lib/spontaneous/render/renderer.rb +46 -0
- data/lib/spontaneous/render.rb +173 -0
- data/lib/spontaneous/revision.rb +7 -0
- data/lib/spontaneous/schema/schema_modification.rb +260 -0
- data/lib/spontaneous/schema/uid.rb +221 -0
- data/lib/spontaneous/schema.rb +295 -0
- data/lib/spontaneous/server.rb +65 -0
- data/lib/spontaneous/site.rb +87 -0
- data/lib/spontaneous/state.rb +53 -0
- data/lib/spontaneous/style.rb +144 -0
- data/lib/spontaneous/tasks/database.rake +9 -0
- data/lib/spontaneous/tasks.rb +5 -0
- data/lib/spontaneous/version.rb +6 -0
- data/lib/spontaneous.rb +179 -0
- data/spontaneous.gemspec.tmpl +66 -0
- data/test/disabled/test_slots.rb +287 -0
- data/test/experimental/test_formats.rb +92 -0
- data/test/experimental/test_plugins.rb +64 -0
- data/test/fixtures/application/css/test.less +5 -0
- data/test/fixtures/application/js/test.js +1 -0
- data/test/fixtures/application/static/favicon.ico +1 -0
- data/test/fixtures/application/static/test.html +1 -0
- data/test/fixtures/application/views/index.erubis +1 -0
- data/test/fixtures/back/public/test.html +1 -0
- data/test/fixtures/back/templates/layouts/standard.html.cut +1 -0
- data/test/fixtures/config/config/environment.rb +4 -0
- data/test/fixtures/config/config/environments/development.rb +13 -0
- data/test/fixtures/config/config/environments/production.rb +22 -0
- data/test/fixtures/config/config/environments/staging.rb +2 -0
- data/test/fixtures/example_application/Gemfile +6 -0
- data/test/fixtures/example_application/Gemfile.lock +76 -0
- data/test/fixtures/example_application/Rakefile +6 -0
- data/test/fixtures/example_application/config/back.rb +15 -0
- data/test/fixtures/example_application/config/back.ru +8 -0
- data/test/fixtures/example_application/config/back.yml +8 -0
- data/test/fixtures/example_application/config/boot.rb +16 -0
- data/test/fixtures/example_application/config/database.yml +24 -0
- data/test/fixtures/example_application/config/environment.rb +4 -0
- data/test/fixtures/example_application/config/environments/development.rb +16 -0
- data/test/fixtures/example_application/config/environments/production.rb +21 -0
- data/test/fixtures/example_application/config/environments/staging.rb +1 -0
- data/test/fixtures/example_application/config/front.rb +8 -0
- data/test/fixtures/example_application/config/front.ru +8 -0
- data/test/fixtures/example_application/config/front.yml +8 -0
- data/test/fixtures/example_application/config/schema.yml +48 -0
- data/test/fixtures/example_application/config/unicorn.rb +1 -0
- data/test/fixtures/example_application/config/user_levels.yml +19 -0
- data/test/fixtures/example_application/public/css/test.css +0 -0
- data/test/fixtures/example_application/public/favicon.ico +1 -0
- data/test/fixtures/example_application/public/js/test.js +0 -0
- data/test/fixtures/example_application/public/test.html +1 -0
- data/test/fixtures/example_application/schema/client_project.rb +18 -0
- data/test/fixtures/example_application/schema/client_projects.rb +8 -0
- data/test/fixtures/example_application/schema/home_page.rb +22 -0
- data/test/fixtures/example_application/schema/info_page.rb +13 -0
- data/test/fixtures/example_application/schema/inline_image.rb +11 -0
- data/test/fixtures/example_application/schema/page.rb +4 -0
- data/test/fixtures/example_application/schema/piece.rb +3 -0
- data/test/fixtures/example_application/schema/project.rb +21 -0
- data/test/fixtures/example_application/schema/project_image.rb +18 -0
- data/test/fixtures/example_application/schema/projects_page.rb +12 -0
- data/test/fixtures/example_application/schema/text.rb +8 -0
- data/test/fixtures/example_application/templates/client_project/images.html.cut +1 -0
- data/test/fixtures/example_application/templates/client_project.html.cut +4 -0
- data/test/fixtures/example_application/templates/client_projects.html.cut +6 -0
- data/test/fixtures/example_application/templates/info_page/inline.html.cut +0 -0
- data/test/fixtures/example_application/templates/inline_image.html.cut +1 -0
- data/test/fixtures/example_application/templates/layouts/home.html.cut +15 -0
- data/test/fixtures/example_application/templates/layouts/info.html.cut +3 -0
- data/test/fixtures/example_application/templates/layouts/project.html.cut +13 -0
- data/test/fixtures/example_application/templates/layouts/projects.html.cut +11 -0
- data/test/fixtures/example_application/templates/layouts/standard.html.cut +0 -0
- data/test/fixtures/example_application/templates/project/inline.html.cut +5 -0
- data/test/fixtures/example_application/templates/project.html.cut +5 -0
- data/test/fixtures/example_application/templates/project_image.html.cut +1 -0
- data/test/fixtures/example_application/templates/text.html.cut +1 -0
- data/test/fixtures/images/rose.greyscale.jpg +0 -0
- data/test/fixtures/images/rose.jpg +0 -0
- data/test/fixtures/images/size.gif +0 -0
- data/test/fixtures/images/size.jpg +0 -0
- data/test/fixtures/images/size.png24 +0 -0
- data/test/fixtures/images/size.png8 +0 -0
- data/test/fixtures/layouts/layouts/custom1.html.cut +1 -0
- data/test/fixtures/layouts/layouts/custom1.pdf.cut +0 -0
- data/test/fixtures/layouts/layouts/custom1.xml.cut +0 -0
- data/test/fixtures/layouts/layouts/custom2.html.cut +1 -0
- data/test/fixtures/layouts/layouts/custom3.html.cut +0 -0
- data/test/fixtures/layouts/layouts/standard.html.cut +1 -0
- data/test/fixtures/media/101/003/rose.jpg +0 -0
- data/test/fixtures/permissions/config/user_levels.yml +9 -0
- data/test/fixtures/permissions/media/image.jpg +0 -0
- data/test/fixtures/plugins/schema_plugin/init.rb +1 -0
- data/test/fixtures/plugins/schema_plugin/schema/external.rb +5 -0
- data/test/fixtures/plugins/schema_plugin/templates/external.html.cut +1 -0
- data/test/fixtures/plugins/schema_plugin/templates/from_plugin.html.cut +0 -0
- data/test/fixtures/plugins/schema_plugin/templates/layouts/from_plugin.html.cut +0 -0
- data/test/fixtures/public/templates/layouts/default.html.cut +1 -0
- data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -0
- data/test/fixtures/public/templates/layouts/default.rss.cut +1 -0
- data/test/fixtures/public/templates/layouts/dynamic.html.cut +1 -0
- data/test/fixtures/public/templates/layouts/standard.html.cut +0 -0
- data/test/fixtures/schema/before.yml +24 -0
- data/test/fixtures/schema/resolvable.yml +12 -0
- data/test/fixtures/schema/schema.yml +7 -0
- data/test/fixtures/serialisation/class_hash.yaml.erb +53 -0
- data/test/fixtures/serialisation/root_hash.yaml.erb +184 -0
- data/test/fixtures/sharding/rose.jpg +0 -0
- data/test/fixtures/sharding/xaa +0 -0
- data/test/fixtures/sharding/xab +0 -0
- data/test/fixtures/sharding/xac +0 -0
- data/test/fixtures/sharding/xad +0 -0
- data/test/fixtures/sharding/xae +0 -0
- data/test/fixtures/sharding/xaf +0 -0
- data/test/fixtures/sharding/xag +0 -0
- data/test/fixtures/styles/box_a/runny.html.cut +0 -0
- data/test/fixtures/styles/box_a.html.cut +1 -0
- data/test/fixtures/styles/named2.html.cut +1 -0
- data/test/fixtures/styles/orange/apple.html.cut +1 -0
- data/test/fixtures/styles/template_class/named1.html.cut +1 -0
- data/test/fixtures/styles/template_class/results.html.cut +1 -0
- data/test/fixtures/styles/template_class/walky.html.cut +0 -0
- data/test/fixtures/styles/template_class.epub.cut +0 -0
- data/test/fixtures/styles/template_class.html.cut +1 -0
- data/test/fixtures/styles/template_class.pdf.cut +0 -0
- data/test/fixtures/styles/template_sub_class1.html.cut +1 -0
- data/test/fixtures/templates/aliases/a/a_style.html.cut +0 -0
- data/test/fixtures/templates/aliases/a/page.html.cut +0 -0
- data/test/fixtures/templates/aliases/a_alias/a_alias_style.html.cut +0 -0
- data/test/fixtures/templates/aliases/layouts/b.html.cut +1 -0
- data/test/fixtures/templates/aliases/layouts/b_alias.html.cut +1 -0
- data/test/fixtures/templates/aliases/layouts/c_alias.html.cut +1 -0
- data/test/fixtures/templates/boxes/blank_content/things.html.cut +1 -0
- data/test/fixtures/templates/boxes/my_box_class/christy.html.cut +1 -0
- data/test/fixtures/templates/boxes/thangs.html.cut +1 -0
- data/test/fixtures/templates/boxes/with_template_box.html.cut +1 -0
- data/test/fixtures/templates/content/include.html.cut +1 -0
- data/test/fixtures/templates/content/include_dir.html.cut +1 -0
- data/test/fixtures/templates/content/included.epub.cut +1 -0
- data/test/fixtures/templates/content/included.html.cut +1 -0
- data/test/fixtures/templates/content/partial/included.html.cut +1 -0
- data/test/fixtures/templates/content/preprocess.html.cut +1 -0
- data/test/fixtures/templates/content/second.html.cut +1 -0
- data/test/fixtures/templates/content/template.epub.cut +1 -0
- data/test/fixtures/templates/content/template.html.cut +1 -0
- data/test/fixtures/templates/default_style_class.html.cut +1 -0
- data/test/fixtures/templates/direct.html.cut +1 -0
- data/test/fixtures/templates/extended/grandparent.html.cut +10 -0
- data/test/fixtures/templates/extended/main.html.cut +6 -0
- data/test/fixtures/templates/extended/parent.html.cut +10 -0
- data/test/fixtures/templates/layouts/entries.html.cut +7 -0
- data/test/fixtures/templates/layouts/page_style.html.cut +1 -0
- data/test/fixtures/templates/layouts/params.html.cut +1 -0
- data/test/fixtures/templates/layouts/preview_render.html.cut +2 -0
- data/test/fixtures/templates/layouts/standard_page.html.cut +1 -0
- data/test/fixtures/templates/layouts/subdir_style.html.cut +1 -0
- data/test/fixtures/templates/layouts/template_params.html.cut +1 -0
- data/test/fixtures/templates/page_class/inline_style.html.cut +1 -0
- data/test/fixtures/templates/preview_render/inline.html.cut +0 -0
- data/test/fixtures/templates/publishing/layouts/dynamic.html.cut +1 -0
- data/test/fixtures/templates/publishing/layouts/static.html.cut +1 -0
- data/test/fixtures/templates/template_class/anonymous_style.html.cut +4 -0
- data/test/fixtures/templates/template_class/another_template.html.cut +0 -0
- data/test/fixtures/templates/template_class/complex_template.html.cut +6 -0
- data/test/fixtures/templates/template_class/complex_template.pdf.cut +6 -0
- data/test/fixtures/templates/template_class/default_template_style.html.cut +4 -0
- data/test/fixtures/templates/template_class/images_with_template.html.cut +5 -0
- data/test/fixtures/templates/template_class/slots_template.html.cut +5 -0
- data/test/fixtures/templates/template_class/slots_template.pdf.cut +5 -0
- data/test/fixtures/templates/template_class/this_template.epub.cut +1 -0
- data/test/fixtures/templates/template_class/this_template.html.cut +1 -0
- data/test/fixtures/templates/template_class/this_template.pdf.cut +1 -0
- data/test/fixtures/templates/with_default_style_class.html.cut +1 -0
- data/test/functional/test_application.rb +176 -0
- data/test/functional/test_back.rb +902 -0
- data/test/functional/test_front.rb +571 -0
- data/test/javascript/test_dom.rb +94 -0
- data/test/javascript/test_markdown.rb +97 -0
- data/test/slow/test_publishing.rb +987 -0
- data/test/slow/test_visibility.rb +250 -0
- data/test/support/custom_matchers.rb +77 -0
- data/test/support/timing.rb +23 -0
- data/test/test_helper.rb +164 -0
- data/test/test_javascript.rb +34 -0
- data/test/ui/test_page_editing.rb +167 -0
- data/test/ui_helper.rb +114 -0
- data/test/unit/test_alias.rb +254 -0
- data/test/unit/test_authentication.rb +510 -0
- data/test/unit/test_boxes.rb +497 -0
- data/test/unit/test_config.rb +156 -0
- data/test/unit/test_content.rb +221 -0
- data/test/unit/test_content_inheritance.rb +103 -0
- data/test/unit/test_extensions.rb +14 -0
- data/test/unit/test_fields.rb +392 -0
- data/test/unit/test_generators.rb +97 -0
- data/test/unit/test_image_size.rb +25 -0
- data/test/unit/test_images.rb +265 -0
- data/test/unit/test_layouts.rb +111 -0
- data/test/unit/test_logger.rb +80 -0
- data/test/unit/test_media.rb +70 -0
- data/test/unit/test_page.rb +244 -0
- data/test/unit/test_permissions.rb +834 -0
- data/test/unit/test_piece.rb +80 -0
- data/test/unit/test_prototype_set.rb +192 -0
- data/test/unit/test_prototypes.rb +102 -0
- data/test/unit/test_render.rb +359 -0
- data/test/unit/test_schema.rb +1009 -0
- data/test/unit/test_serialisation.rb +215 -0
- data/test/unit/test_site.rb +145 -0
- data/test/unit/test_structure.rb +85 -0
- data/test/unit/test_styles.rb +417 -0
- data/test/unit/test_templates.rb +224 -0
- data/test/unit/test_type_hierarchy.rb +28 -0
- metadata +1017 -0
|
@@ -0,0 +1,1009 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SchemaTest < MiniTest::Spec
|
|
7
|
+
include Spontaneous
|
|
8
|
+
|
|
9
|
+
UID = Spontaneous::Schema::UID
|
|
10
|
+
|
|
11
|
+
# declare these early so that Piece & Page get loaded
|
|
12
|
+
# and are then cleared early by the Schema.reset! call
|
|
13
|
+
class X < Spontaneous::Piece; end
|
|
14
|
+
class Y < Spontaneous::Page; end
|
|
15
|
+
def setup
|
|
16
|
+
Spontaneous::Schema.schema_loader_class = Spontaneous::Schema::PersistentMap
|
|
17
|
+
Spontaneous::Schema.reset!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "Configurable names" do
|
|
21
|
+
setup do
|
|
22
|
+
class ::FunkyContent < Content; end
|
|
23
|
+
class ::MoreFunkyContent < FunkyContent; end
|
|
24
|
+
class ::ABCDifficultName < Content; end
|
|
25
|
+
|
|
26
|
+
class ::CustomName < ABCDifficultName
|
|
27
|
+
title "Some Name"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
teardown do
|
|
32
|
+
[:FunkyContent, :MoreFunkyContent, :ABCDifficultName, :CustomName].each do |klass|
|
|
33
|
+
Object.send(:remove_const, klass)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
should "default to generated version" do
|
|
38
|
+
FunkyContent.default_title.should == "Funky Content"
|
|
39
|
+
FunkyContent.title.should == "Funky Content"
|
|
40
|
+
MoreFunkyContent.title.should == "More Funky Content"
|
|
41
|
+
ABCDifficultName.default_title.should == "ABC Difficult Name"
|
|
42
|
+
ABCDifficultName.title.should == "ABC Difficult Name"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
should "be settable" do
|
|
46
|
+
CustomName.title.should == "Some Name"
|
|
47
|
+
FunkyContent.title "Content Class"
|
|
48
|
+
FunkyContent.title.should == "Content Class"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
should "be settable using =" do
|
|
52
|
+
FunkyContent.title = "Content Class"
|
|
53
|
+
FunkyContent.title.should == "Content Class"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
should "not inherit from superclass" do
|
|
57
|
+
FunkyContent.title = "Custom Name"
|
|
58
|
+
MoreFunkyContent.title.should == "More Funky Content"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context "Persistent maps" do
|
|
63
|
+
context "Schema UIDs" do
|
|
64
|
+
setup do
|
|
65
|
+
Spontaneous.schema_map = File.expand_path('../../fixtures/schema/schema.yml', __FILE__)
|
|
66
|
+
class SchemaClass < Page
|
|
67
|
+
field :description
|
|
68
|
+
style :simple
|
|
69
|
+
layout :clean
|
|
70
|
+
box :posts
|
|
71
|
+
end
|
|
72
|
+
@instance = SchemaClass.new
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
teardown do
|
|
76
|
+
SchemaTest.send(:remove_const, :SchemaClass) rescue nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# should "be 12 characters long" do
|
|
80
|
+
# Schema::UID.generate.to_s.length.should == 12
|
|
81
|
+
# end
|
|
82
|
+
|
|
83
|
+
should "be unique" do
|
|
84
|
+
ids = (0..10000).map { Schema::UID.generate }
|
|
85
|
+
ids.uniq.length.should == ids.length
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
should "be singletons" do
|
|
89
|
+
a = UID["xxxxxxxxxxxx"]
|
|
90
|
+
b = UID["xxxxxxxxxxxx"]
|
|
91
|
+
c = UID["ffffffffffff"]
|
|
92
|
+
a.object_id.should == b.object_id
|
|
93
|
+
a.should == b
|
|
94
|
+
c.object_id.should_not == b.object_id
|
|
95
|
+
c.should_not == b
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
should "not be creatable" do
|
|
99
|
+
lambda { UID.new('sadf') }.must_raise(NoMethodError)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
should "return nil if passed nil" do
|
|
103
|
+
UID[nil].should be_nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
should "return nil if passed an empty string" do
|
|
107
|
+
UID[""].should be_nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
should "return the same UID if passed one" do
|
|
111
|
+
a = UID["xxxxxxxxxxxx"]
|
|
112
|
+
UID[a].should == a
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
should "test as equal to its string representation" do
|
|
116
|
+
UID["llllllllllll"].should == "llllllllllll"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
should "be readable by content classes" do
|
|
120
|
+
SchemaClass.schema_id.should == UID["xxxxxxxxxxxx"]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
should "be readable by fields" do
|
|
124
|
+
@instance.fields[:description].schema_id.should == UID["ffffffffffff"]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
should "be readable by boxes" do
|
|
128
|
+
@instance.boxes[:posts].schema_id.should == UID["bbbbbbbbbbbb"]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
should "be readable by styles" do
|
|
132
|
+
@instance.styles[:simple].schema_id.should == UID["ssssssssssss"]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
should "be readable by layouts" do
|
|
136
|
+
@instance.layout.name.should == :clean
|
|
137
|
+
@instance.layout.schema_id.should == UID["llllllllllll"]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context "lookups" do
|
|
141
|
+
should "return classes" do
|
|
142
|
+
Schema["xxxxxxxxxxxx"].should == SchemaClass
|
|
143
|
+
end
|
|
144
|
+
should "return fields" do
|
|
145
|
+
Schema["ffffffffffff"].should == SchemaClass.field_prototypes[:description]
|
|
146
|
+
end
|
|
147
|
+
should "return boxes" do
|
|
148
|
+
Schema["bbbbbbbbbbbb"].should == SchemaClass.box_prototypes[:posts]
|
|
149
|
+
end
|
|
150
|
+
should "return styles" do
|
|
151
|
+
Schema["ssssssssssss"].should == SchemaClass.style_prototypes[:simple]
|
|
152
|
+
end
|
|
153
|
+
should "return layouts" do
|
|
154
|
+
Schema["llllllllllll"].should == SchemaClass.layout_prototypes[:clean]
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context "schema verification" do
|
|
160
|
+
setup do
|
|
161
|
+
Spontaneous.schema_map = File.expand_path('../../fixtures/schema/before.yml', __FILE__)
|
|
162
|
+
class ::Page < Spontaneous::Page
|
|
163
|
+
field :title
|
|
164
|
+
end
|
|
165
|
+
class B < ::Page; end
|
|
166
|
+
class C < Content; end
|
|
167
|
+
class D < Content; end
|
|
168
|
+
class O < Box; end
|
|
169
|
+
B.field :description
|
|
170
|
+
B.field :author
|
|
171
|
+
B.box :promotions do
|
|
172
|
+
field :field1
|
|
173
|
+
field :field2
|
|
174
|
+
style :style1
|
|
175
|
+
style :style2
|
|
176
|
+
end
|
|
177
|
+
B.box :publishers, :type => O
|
|
178
|
+
B.style :inline
|
|
179
|
+
B.style :outline
|
|
180
|
+
B.layout :thin
|
|
181
|
+
B.layout :fat
|
|
182
|
+
|
|
183
|
+
O.field :ofield1
|
|
184
|
+
O.field :ofield2
|
|
185
|
+
O.style :ostyle1
|
|
186
|
+
O.style :ostyle2
|
|
187
|
+
|
|
188
|
+
# have to use mocking because schema class list is totally fecked up
|
|
189
|
+
# after running other tests
|
|
190
|
+
# TODO: look into reliable, non-harmful way of clearing out the schema state
|
|
191
|
+
# between tests
|
|
192
|
+
# Schema.stubs(:classes).returns([B, C, D, O])
|
|
193
|
+
# Schema.classes.should == [B, C, D, O]
|
|
194
|
+
::Page.schema_id.should == UID["tttttttttttt"]
|
|
195
|
+
B.schema_id.should == UID["bbbbbbbbbbbb"]
|
|
196
|
+
C.schema_id.should == UID["cccccccccccc"]
|
|
197
|
+
D.schema_id.should == UID["dddddddddddd"]
|
|
198
|
+
O.schema_id.should == UID["oooooooooooo"]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
teardown do
|
|
202
|
+
Object.send(:remove_const, :Page) rescue nil
|
|
203
|
+
SchemaTest.send(:remove_const, :B) rescue nil
|
|
204
|
+
SchemaTest.send(:remove_const, :C) rescue nil
|
|
205
|
+
SchemaTest.send(:remove_const, :D) rescue nil
|
|
206
|
+
SchemaTest.send(:remove_const, :E) rescue nil
|
|
207
|
+
SchemaTest.send(:remove_const, :F) rescue nil
|
|
208
|
+
SchemaTest.send(:remove_const, :O) rescue nil
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
should "return the right schema anme for inherited box fields" do
|
|
212
|
+
f = B.boxes[:publishers].instance_class.field :newfield
|
|
213
|
+
B.boxes[:publishers].instance_class.fields.first.schema_name.should == "field/oooooooooooo/ofield1"
|
|
214
|
+
f.schema_name.should == "field/publishers00/newfield"
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
should "detect addition of classes" do
|
|
218
|
+
class E < Content; end
|
|
219
|
+
Schema.stubs(:classes).returns([B, C, D, E])
|
|
220
|
+
exception = nil
|
|
221
|
+
begin
|
|
222
|
+
Schema.validate_schema
|
|
223
|
+
flunk("Validation should raise an exception")
|
|
224
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
225
|
+
exception = e
|
|
226
|
+
end
|
|
227
|
+
exception.added_classes.should == [E]
|
|
228
|
+
# need to explicitly define solution to validation error
|
|
229
|
+
# Schema.expects(:generate).returns('dddddddddddd')
|
|
230
|
+
# D.schema_id.should == 'dddddddddddd'
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
should "detect removal of classes" do
|
|
234
|
+
SchemaTest.send(:remove_const, :C) rescue nil
|
|
235
|
+
SchemaTest.send(:remove_const, :D) rescue nil
|
|
236
|
+
Schema.stubs(:classes).returns([::Page, B, O])
|
|
237
|
+
begin
|
|
238
|
+
Schema.validate_schema
|
|
239
|
+
flunk("Validation should raise an exception")
|
|
240
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
241
|
+
exception = e
|
|
242
|
+
end
|
|
243
|
+
exception.removed_classes.map { |c| c.name }.sort.should == ["SchemaTest::C", "SchemaTest::D"]
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
should "detect multiple removals & additions of classes" do
|
|
247
|
+
SchemaTest.send(:remove_const, :C) rescue nil
|
|
248
|
+
SchemaTest.send(:remove_const, :D) rescue nil
|
|
249
|
+
class E < Content; end
|
|
250
|
+
class F < Content; end
|
|
251
|
+
Schema.stubs(:classes).returns([::Page, B, E, F, O])
|
|
252
|
+
begin
|
|
253
|
+
Schema.validate_schema
|
|
254
|
+
flunk("Validation should raise an exception if schema is modified")
|
|
255
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
256
|
+
exception = e
|
|
257
|
+
end
|
|
258
|
+
exception.added_classes.should == [E, F]
|
|
259
|
+
exception.removed_classes.map {|c| c.name}.sort.should == ["SchemaTest::C", "SchemaTest::D"]
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
should "detect addition of fields" do
|
|
263
|
+
B.field :name
|
|
264
|
+
C.field :location
|
|
265
|
+
C.field :description
|
|
266
|
+
begin
|
|
267
|
+
Schema.validate_schema
|
|
268
|
+
flunk("Validation should raise an exception if new fields are added")
|
|
269
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
270
|
+
exception = e
|
|
271
|
+
end
|
|
272
|
+
exception.added_fields.should == [B.field_prototypes[:name], C.field_prototypes[:location], C.field_prototypes[:description]]
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
should "detect removal of fields" do
|
|
276
|
+
field = B.field_prototypes[:author]
|
|
277
|
+
B.stubs(:field_prototypes).returns({:author => field})
|
|
278
|
+
B.stubs(:fields).returns([field])
|
|
279
|
+
begin
|
|
280
|
+
Schema.validate_schema
|
|
281
|
+
flunk("Validation should raise an exception if fields are removed")
|
|
282
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
283
|
+
exception = e
|
|
284
|
+
end
|
|
285
|
+
exception.removed_fields.length == 1
|
|
286
|
+
exception.removed_fields[0].name.should == "description"
|
|
287
|
+
exception.removed_fields[0].owner.should == SchemaTest::B
|
|
288
|
+
exception.removed_fields[0].category.should == :field
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
should "detect addition of boxes" do
|
|
292
|
+
B.box :changes
|
|
293
|
+
B.box :updates
|
|
294
|
+
begin
|
|
295
|
+
Schema.validate_schema
|
|
296
|
+
flunk("Validation should raise an exception if new boxes are added")
|
|
297
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
298
|
+
exception = e
|
|
299
|
+
end
|
|
300
|
+
exception.added_boxes.should == [B.boxes[:changes], B.boxes[:updates]]
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
should "detect removal of boxes" do
|
|
304
|
+
boxes = S::Collections::PrototypeSet.new
|
|
305
|
+
boxes[:promotions] = B.boxes[:promotions]
|
|
306
|
+
|
|
307
|
+
B.stubs(:box_prototypes).returns(boxes)
|
|
308
|
+
begin
|
|
309
|
+
Schema.validate_schema
|
|
310
|
+
flunk("Validation should raise an exception if fields are removed")
|
|
311
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
312
|
+
exception = e
|
|
313
|
+
end
|
|
314
|
+
exception.removed_boxes.length.should == 1
|
|
315
|
+
exception.removed_boxes[0].name.should == "publishers"
|
|
316
|
+
exception.removed_boxes[0].owner.should == SchemaTest::B
|
|
317
|
+
exception.removed_boxes[0].category.should == :box
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
should "detect addition of styles" do
|
|
321
|
+
B.style :fancy
|
|
322
|
+
B.style :dirty
|
|
323
|
+
begin
|
|
324
|
+
Schema.validate_schema
|
|
325
|
+
flunk("Validation should raise an exception if new styles are added")
|
|
326
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
327
|
+
exception = e
|
|
328
|
+
end
|
|
329
|
+
exception.added_styles.should == [B.styles.detect{ |s| s.name == :fancy }, B.styles.detect{ |s| s.name == :dirty }]
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
should "detect removal of styles" do
|
|
333
|
+
style = B.styles[:inline]
|
|
334
|
+
B.styles.expects(:order).returns([:inline])
|
|
335
|
+
B.styles.stubs(:[]).with(:inline).returns(style)
|
|
336
|
+
B.styles.stubs(:[]).with(:outline).returns(nil)
|
|
337
|
+
begin
|
|
338
|
+
Schema.validate_schema
|
|
339
|
+
flunk("Validation should raise an exception if styles are removed")
|
|
340
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
341
|
+
exception = e
|
|
342
|
+
end
|
|
343
|
+
exception.removed_styles.length.should == 1
|
|
344
|
+
exception.removed_styles[0].name.should == "outline"
|
|
345
|
+
exception.removed_styles[0].owner.should == SchemaTest::B
|
|
346
|
+
exception.removed_styles[0].category.should == :style
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
should "detect addition of layouts" do
|
|
350
|
+
B.layout :fancy
|
|
351
|
+
B.layout :dirty
|
|
352
|
+
begin
|
|
353
|
+
Schema.validate_schema
|
|
354
|
+
flunk("Validation should raise an exception if new layouts are added")
|
|
355
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
356
|
+
exception = e
|
|
357
|
+
end
|
|
358
|
+
exception.added_layouts.should == [B.layouts.detect{ |s| s.name == :fancy }, B.layouts.detect{ |s| s.name == :dirty }]
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
should "detect removal of layouts" do
|
|
362
|
+
layout = B.layouts[:thin]
|
|
363
|
+
B.layouts.expects(:order).returns([:thin])
|
|
364
|
+
B.layouts.stubs(:[]).with(:thin).returns(layout)
|
|
365
|
+
B.layouts.stubs(:[]).with(:fat).returns(nil)
|
|
366
|
+
begin
|
|
367
|
+
Schema.validate_schema
|
|
368
|
+
flunk("Validation should raise an exception if fields are removed")
|
|
369
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
370
|
+
exception = e
|
|
371
|
+
end
|
|
372
|
+
exception.removed_layouts.length.should == 1
|
|
373
|
+
exception.removed_layouts[0].name.should == "fat"
|
|
374
|
+
exception.removed_layouts[0].owner.should == SchemaTest::B
|
|
375
|
+
exception.removed_layouts[0].category.should == :layout
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
should "detect addition of fields to anonymous boxes" do
|
|
379
|
+
f1 = B.boxes[:publishers].instance_class.field :field3
|
|
380
|
+
f2 = B.boxes[:promotions].instance_class.field :field3
|
|
381
|
+
begin
|
|
382
|
+
Schema.validate_schema
|
|
383
|
+
flunk("Validation should raise an exception if new fields are added to anonymous boxes")
|
|
384
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
385
|
+
exception = e
|
|
386
|
+
end
|
|
387
|
+
assert_same_elements exception.added_fields, [f2, f1]
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
should "detect removal of fields from anonymous boxes" do
|
|
391
|
+
f2 = B.boxes[:promotions].instance_class.field_prototypes[:field2]
|
|
392
|
+
B.boxes[:promotions].instance_class.stubs(:field_prototypes).returns({:field2 => f2})
|
|
393
|
+
B.boxes[:promotions].instance_class.stubs(:fields).returns([f2])
|
|
394
|
+
begin
|
|
395
|
+
Schema.validate_schema
|
|
396
|
+
flunk("Validation should raise an exception if fields are removed from anonymous boxes")
|
|
397
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
398
|
+
exception = e
|
|
399
|
+
end
|
|
400
|
+
exception.removed_fields.length.should == 1
|
|
401
|
+
exception.removed_fields[0].name.should == "field1"
|
|
402
|
+
exception.removed_fields[0].owner.instance_class.should == SchemaTest::B.boxes[:promotions].instance_class
|
|
403
|
+
exception.removed_fields[0].category.should == :field
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
should "detect addition of fields to box types" do
|
|
407
|
+
O.field :name
|
|
408
|
+
begin
|
|
409
|
+
Schema.validate_schema
|
|
410
|
+
flunk("Validation should raise an exception if new fields are added to boxes")
|
|
411
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
412
|
+
exception = e
|
|
413
|
+
end
|
|
414
|
+
exception.added_fields.should == [O.field_prototypes[:name]]
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# should "detect removal of fields from box types" do
|
|
418
|
+
# skip "stubbing is messing up the field hierarchy in weird ways"
|
|
419
|
+
# fields = [O.field_prototypes[:ofield1]]
|
|
420
|
+
# O.stubs(:fields).returns(fields)
|
|
421
|
+
# begin
|
|
422
|
+
# Schema.validate_schema
|
|
423
|
+
# flunk("Validation should raise an exception if fields are removed")
|
|
424
|
+
# rescue Spontaneous::SchemaModificationError => e
|
|
425
|
+
# exception = e
|
|
426
|
+
# end
|
|
427
|
+
# exception.removed_fields.length == 1
|
|
428
|
+
# exception.removed_fields[0].name.should == "ofield2"
|
|
429
|
+
# exception.removed_fields[0].owner.should == SchemaTest::O
|
|
430
|
+
# exception.removed_fields[0].category.should == :field
|
|
431
|
+
# end
|
|
432
|
+
|
|
433
|
+
should "detect addition of styles to box types"
|
|
434
|
+
should "detect removal of styles from box types"
|
|
435
|
+
|
|
436
|
+
should "detect addition of styles to anonymous boxes" do
|
|
437
|
+
s1 = B.boxes[:publishers].instance_class.style :style3
|
|
438
|
+
s2 = B.boxes[:promotions].instance_class.style :style3
|
|
439
|
+
begin
|
|
440
|
+
Schema.validate_schema
|
|
441
|
+
flunk("Validation should raise an exception if new fields are added to anonymous boxes")
|
|
442
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
443
|
+
exception = e
|
|
444
|
+
end
|
|
445
|
+
assert_same_elements exception.added_styles, [s2, s1]
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
should "detect removal of styles from anonymous boxes" do
|
|
449
|
+
klass = B.boxes[:promotions].instance_class
|
|
450
|
+
style = klass.styles.first
|
|
451
|
+
klass.styles.expects(:order).returns([style.name])
|
|
452
|
+
klass.styles.stubs(:[]).with(style.name).returns(style)
|
|
453
|
+
klass.styles.stubs(:[]).with(:style2).returns(nil)
|
|
454
|
+
begin
|
|
455
|
+
Schema.validate_schema
|
|
456
|
+
flunk("Validation should raise an exception if styles are removed")
|
|
457
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
458
|
+
exception = e
|
|
459
|
+
end
|
|
460
|
+
exception.removed_styles.length.should == 1
|
|
461
|
+
exception.removed_styles[0].name.should == "style2"
|
|
462
|
+
exception.removed_styles[0].owner.instance_class.should == SchemaTest::B.boxes[:promotions].instance_class
|
|
463
|
+
exception.removed_styles[0].category.should == :style
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
context "Transient (testing) maps" do
|
|
468
|
+
setup do
|
|
469
|
+
Spontaneous::Schema.schema_loader_class = Spontaneous::Schema::TransientMap
|
|
470
|
+
Spontaneous::Schema.reset!
|
|
471
|
+
class V < Spontaneous::Piece; end
|
|
472
|
+
class W < Spontaneous::Piece; end
|
|
473
|
+
end
|
|
474
|
+
teardown do
|
|
475
|
+
self.class.send(:remove_const, :V)
|
|
476
|
+
self.class.send(:remove_const, :W)
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
should "create uids on demand" do
|
|
480
|
+
V.schema_id.should_not be_nil
|
|
481
|
+
W.schema_id.should_not be_nil
|
|
482
|
+
V.schema_id.should_not == W.schema_id
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
should "return consistent ids within a session" do
|
|
486
|
+
a = V.schema_id
|
|
487
|
+
b = V.schema_id
|
|
488
|
+
a.should equal?(b)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
should "return UID objects" do
|
|
492
|
+
V.schema_id.must_be_instance_of(Spontaneous::Schema::UID)
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
context "Map writing" do
|
|
497
|
+
context "Non-existant maps" do
|
|
498
|
+
setup do
|
|
499
|
+
S::Schema.reset!
|
|
500
|
+
@map_file = File.expand_path('../../../tmp/schema.yml', __FILE__)
|
|
501
|
+
::File.exists?(@map_file).should be_false
|
|
502
|
+
Spontaneous.schema_map = @map_file
|
|
503
|
+
class ::A < Spontaneous::Page
|
|
504
|
+
field :title
|
|
505
|
+
field :introduction
|
|
506
|
+
layout :sparse
|
|
507
|
+
box :posts do
|
|
508
|
+
field :description
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
class ::B < Spontaneous::Piece
|
|
512
|
+
field :location
|
|
513
|
+
style :daring
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
teardown do
|
|
517
|
+
Object.send(:remove_const, :A) rescue nil
|
|
518
|
+
Object.send(:remove_const, :B) rescue nil
|
|
519
|
+
FileUtils.rm(@map_file) if ::File.exists?(@map_file)
|
|
520
|
+
end
|
|
521
|
+
should "get created with verification" do
|
|
522
|
+
S::Schema.validate!
|
|
523
|
+
classes = [ ::A, ::B]
|
|
524
|
+
# would like to do all of this using mocks, but don't know how to do that
|
|
525
|
+
# without fecking up the whole schema id creation process
|
|
526
|
+
expected = Hash[ classes.map { |klass| [ klass.schema_id.to_s, klass.schema_name ] } ]
|
|
527
|
+
expected.merge!({
|
|
528
|
+
A.field_prototypes[:title].schema_id.to_s => A.field_prototypes[:title].schema_name,
|
|
529
|
+
A.field_prototypes[:introduction].schema_id.to_s => A.field_prototypes[:introduction].schema_name,
|
|
530
|
+
A.layout_prototypes[:sparse].schema_id.to_s => A.layout_prototypes[:sparse].schema_name,
|
|
531
|
+
A.boxes[:posts].schema_id.to_s => A.boxes[:posts].schema_name,
|
|
532
|
+
A.boxes[:posts].field_prototypes[:description].schema_id.to_s => A.boxes[:posts].field_prototypes[:description].schema_name,
|
|
533
|
+
B.field_prototypes[:location].schema_id.to_s => B.field_prototypes[:location].schema_name,
|
|
534
|
+
B.style_prototypes[:daring].schema_id.to_s => B.style_prototypes[:daring].schema_name,
|
|
535
|
+
})
|
|
536
|
+
File.exists?(@map_file).should be_true
|
|
537
|
+
YAML.load_file(@map_file).should == expected
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
context "change resolution" do
|
|
541
|
+
setup do
|
|
542
|
+
S::Schema.reset!
|
|
543
|
+
@map_file = File.expand_path('../../../tmp/schema.yml', __FILE__)
|
|
544
|
+
FileUtils.mkdir_p(File.dirname(@map_file))
|
|
545
|
+
FileUtils.cp(File.expand_path('../../fixtures/schema/resolvable.yml', __FILE__), @map_file)
|
|
546
|
+
Spontaneous.schema_map = @map_file
|
|
547
|
+
class ::A < Spontaneous::Page
|
|
548
|
+
field :title
|
|
549
|
+
field :introduction
|
|
550
|
+
layout :sparse
|
|
551
|
+
box :posts do
|
|
552
|
+
field :description
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
class ::B < Spontaneous::Piece
|
|
556
|
+
field :location
|
|
557
|
+
field :duration
|
|
558
|
+
style :daring
|
|
559
|
+
end
|
|
560
|
+
S::Schema.validate!
|
|
561
|
+
A.schema_id.should == S::Schema::UID["qLcxinA008"]
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
teardown do
|
|
565
|
+
Object.send(:remove_const, :A) rescue nil
|
|
566
|
+
Object.send(:remove_const, :B) rescue nil
|
|
567
|
+
Object.send(:remove_const, :X) rescue nil
|
|
568
|
+
Object.send(:remove_const, :Y) rescue nil
|
|
569
|
+
S::Content.delete
|
|
570
|
+
FileUtils.rm(@map_file) if ::File.exists?(@map_file)
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
should "be done automatically if only additions are found" do
|
|
574
|
+
A.field :moose
|
|
575
|
+
class ::X < ::A
|
|
576
|
+
field :wild
|
|
577
|
+
box :monkeys do
|
|
578
|
+
field :banana
|
|
579
|
+
end
|
|
580
|
+
layout :rich
|
|
581
|
+
end
|
|
582
|
+
class ::Y < ::B
|
|
583
|
+
style :risky
|
|
584
|
+
end
|
|
585
|
+
S::Schema.validate!
|
|
586
|
+
::X.schema_id.should_not be_nil
|
|
587
|
+
::Y.schema_id.should_not be_nil
|
|
588
|
+
::A.field_prototypes[:moose].schema_id.should_not be_nil
|
|
589
|
+
|
|
590
|
+
m = YAML.load_file(@map_file)
|
|
591
|
+
m[::A.field_prototypes[:moose].schema_id.to_s].should == ::A.field_prototypes[:moose].schema_name
|
|
592
|
+
m[::X.schema_id.to_s].should == ::X.schema_name
|
|
593
|
+
m[::Y.schema_id.to_s].should == ::Y.schema_name
|
|
594
|
+
m[::X.field_prototypes[:wild].schema_id.to_s].should == ::X.field_prototypes[:wild].schema_name
|
|
595
|
+
m[::X.boxes[:monkeys].schema_id.to_s].should == ::X.boxes[:monkeys].schema_name
|
|
596
|
+
m[::X.boxes[:monkeys].field_prototypes[:banana].schema_id.to_s].should == ::X.boxes[:monkeys].field_prototypes[:banana].schema_name
|
|
597
|
+
m[::X.layout_prototypes[:rich].schema_id.to_s].should == ::X.layout_prototypes[:rich].schema_name
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
should "be done automatically if only classes have been removed" do
|
|
602
|
+
uid = B.schema_id.to_s
|
|
603
|
+
Object.send(:remove_const, :B)
|
|
604
|
+
S::Schema.stubs(:classes).returns([::A])
|
|
605
|
+
S::Schema.reload!
|
|
606
|
+
S::Schema.validate!
|
|
607
|
+
m = YAML.load_file(@map_file)
|
|
608
|
+
m.key?(uid).should be_false
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
should "be done automatically if only boxes have been removed" do
|
|
612
|
+
uid = A.boxes[:posts].schema_id.to_s
|
|
613
|
+
A.stubs(:box_prototypes).returns(S::Collections::PrototypeSet.new)
|
|
614
|
+
S::Schema.stubs(:classes).returns([A, B])
|
|
615
|
+
S::Schema.reload!
|
|
616
|
+
S::Schema.validate!
|
|
617
|
+
m = YAML.load_file(@map_file)
|
|
618
|
+
m.key?(uid).should be_false
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
should "be done automatically if only fields have been removed" do
|
|
622
|
+
f1 = A.field_prototypes[:title]
|
|
623
|
+
uid = f1.schema_id.to_s
|
|
624
|
+
f2 = A.field_prototypes[:introduction]
|
|
625
|
+
A.stubs(:field_prototypes).returns({:introduction => f2})
|
|
626
|
+
A.stubs(:fields).returns([f2])
|
|
627
|
+
S::Schema.reload!
|
|
628
|
+
S::Schema.validate!
|
|
629
|
+
m = YAML.load_file(@map_file)
|
|
630
|
+
m.key?(uid).should be_false
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
should "be done automatically in presence of independent addition inside type and of type" do
|
|
634
|
+
A.field :moose
|
|
635
|
+
uid = B.schema_id.to_s
|
|
636
|
+
Object.send(:remove_const, :B)
|
|
637
|
+
S::Schema.stubs(:classes).returns([::A])
|
|
638
|
+
S::Schema.reload!
|
|
639
|
+
S::Schema.validate!
|
|
640
|
+
::A.field_prototypes[:moose].schema_id.should_not be_nil
|
|
641
|
+
|
|
642
|
+
m = YAML.load_file(@map_file)
|
|
643
|
+
m[::A.field_prototypes[:moose].schema_id.to_s].should == ::A.field_prototypes[:moose].schema_name
|
|
644
|
+
m.key?(uid).should be_false
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
should "be done automatically in presence of independent addition & removal of fields" do
|
|
648
|
+
A.field :moose
|
|
649
|
+
f1 = B.field_prototypes[:location]
|
|
650
|
+
uid = f1.schema_id.to_s
|
|
651
|
+
f2 = B.field_prototypes[:duration]
|
|
652
|
+
B.stubs(:field_prototypes).returns({:duration => f2})
|
|
653
|
+
B.stubs(:fields).returns([f2])
|
|
654
|
+
S::Schema.reload!
|
|
655
|
+
S::Schema.validate!
|
|
656
|
+
|
|
657
|
+
::A.field_prototypes[:moose].schema_id.should_not be_nil
|
|
658
|
+
|
|
659
|
+
m = YAML.load_file(@map_file)
|
|
660
|
+
m[::A.field_prototypes[:moose].schema_id.to_s].should == ::A.field_prototypes[:moose].schema_name
|
|
661
|
+
m.key?(uid).should be_false
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
should "be done automatically in presence of independent changes to boxes & fields" do
|
|
665
|
+
B.field :crisis
|
|
666
|
+
uid = A.boxes[:posts].schema_id.to_s
|
|
667
|
+
A.stubs(:box_prototypes).returns(S::Collections::PrototypeSet.new)
|
|
668
|
+
S::Schema.stubs(:classes).returns([A, B])
|
|
669
|
+
S::Schema.reload!
|
|
670
|
+
S::Schema.validate!
|
|
671
|
+
|
|
672
|
+
::B.field_prototypes[:crisis].schema_id.should_not be_nil
|
|
673
|
+
m = YAML.load_file(@map_file)
|
|
674
|
+
m.key?(uid).should be_false
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
should "be done automatically in presence of independent changes to classes, boxes & fields" do
|
|
678
|
+
class ::X < B; end
|
|
679
|
+
uid = A.boxes[:posts].schema_id.to_s
|
|
680
|
+
A.stubs(:box_prototypes).returns(S::Collections::PrototypeSet.new)
|
|
681
|
+
B.field :crisis
|
|
682
|
+
B.box :circus
|
|
683
|
+
A.field :crisis
|
|
684
|
+
S::Schema.stubs(:classes).returns([::A, ::B, ::X])
|
|
685
|
+
S::Schema.reload!
|
|
686
|
+
S::Schema.validate!
|
|
687
|
+
|
|
688
|
+
::A.field_prototypes[:crisis].schema_id.should_not be_nil
|
|
689
|
+
m = YAML.load_file(@map_file)
|
|
690
|
+
|
|
691
|
+
box = ::B.boxes[:circus]
|
|
692
|
+
m[box.schema_id.to_s].should == box.schema_name
|
|
693
|
+
|
|
694
|
+
field = ::A.field_prototypes[:crisis]
|
|
695
|
+
m[field.schema_id.to_s].should == field.schema_name
|
|
696
|
+
|
|
697
|
+
field = ::B.field_prototypes[:crisis]
|
|
698
|
+
m[field.schema_id.to_s].should == field.schema_name
|
|
699
|
+
|
|
700
|
+
m.key?(uid).should be_false
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
# sanity check
|
|
705
|
+
should "still raise error in case of addition & deletion" do
|
|
706
|
+
A.field :added
|
|
707
|
+
f1 = A.field_prototypes[:title]
|
|
708
|
+
f2 = A.field_prototypes[:added]
|
|
709
|
+
uid = f1.schema_id.to_s
|
|
710
|
+
f3 = A.field_prototypes[:introduction]
|
|
711
|
+
A.stubs(:field_prototypes).returns({:added => f2, :introduction => f3})
|
|
712
|
+
A.stubs(:fields).returns([f2, f3])
|
|
713
|
+
S::Schema.reload!
|
|
714
|
+
lambda { S::Schema.validate! }.must_raise(Spontaneous::SchemaModificationError)
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
should "still raise error in case of addition & deletion of classes" do
|
|
718
|
+
class ::X < A; end
|
|
719
|
+
uid = B.schema_id.to_s
|
|
720
|
+
Object.send(:remove_const, :B)
|
|
721
|
+
S::Schema.stubs(:classes).returns([::A, ::X])
|
|
722
|
+
S::Schema.reload!
|
|
723
|
+
lambda { S::Schema.validate! }.must_raise(Spontaneous::SchemaModificationError)
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
should "delete box content when a box is removed" do
|
|
727
|
+
instance = A.new
|
|
728
|
+
piece1 = B.new
|
|
729
|
+
piece2 = B.new
|
|
730
|
+
instance.posts << piece1
|
|
731
|
+
instance.posts << piece2
|
|
732
|
+
instance.save
|
|
733
|
+
instance = S::Content[instance.id]
|
|
734
|
+
instance.posts.pieces.length.should == 2
|
|
735
|
+
Content.count.should == 3
|
|
736
|
+
uid = A.boxes[:posts].schema_id.to_s
|
|
737
|
+
A.stubs(:box_prototypes).returns(S::Collections::PrototypeSet.new)
|
|
738
|
+
S::Schema.stubs(:classes).returns([A, B])
|
|
739
|
+
S::Schema.reload!
|
|
740
|
+
S::Schema.validate!
|
|
741
|
+
Content.count.should == 1
|
|
742
|
+
S::Content[instance.id].should == instance
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
context "which isn't automatically resolvable" do
|
|
746
|
+
context "with one field removed" do
|
|
747
|
+
setup do
|
|
748
|
+
A.field :a
|
|
749
|
+
A.field :b
|
|
750
|
+
@df1 = A.field_prototypes[:title]
|
|
751
|
+
@af1 = A.field_prototypes[:a]
|
|
752
|
+
@af2 = A.field_prototypes[:b]
|
|
753
|
+
@uid = @df1.schema_id.to_s
|
|
754
|
+
@f3 = A.field_prototypes[:introduction]
|
|
755
|
+
A.stubs(:field_prototypes).returns({:a => @af1, :b => @af2, :introduction => @f3})
|
|
756
|
+
A.stubs(:fields).returns([@af1, @af2, @f3])
|
|
757
|
+
S::Schema.reload!
|
|
758
|
+
begin
|
|
759
|
+
S::Schema.validate!
|
|
760
|
+
flunk("Validation should raise error when adding & deleting fields")
|
|
761
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
762
|
+
@modification = e.modification
|
|
763
|
+
end
|
|
764
|
+
end
|
|
765
|
+
should "return list of solutions for removal of one field" do
|
|
766
|
+
# add :a, :b, delete :title
|
|
767
|
+
# add :b, rename :title => :a
|
|
768
|
+
# add :a, rename :title => :b
|
|
769
|
+
@modification.actions.description.should =~ /field 'title'/
|
|
770
|
+
@modification.actions.length.should == 3
|
|
771
|
+
action = @modification.actions[0]
|
|
772
|
+
action.action.should == :delete
|
|
773
|
+
action.source.should == @df1.schema_id
|
|
774
|
+
action.description.should =~ /delete field 'title'/i
|
|
775
|
+
action = @modification.actions[1]
|
|
776
|
+
action.action.should == :rename
|
|
777
|
+
action.source.should == @df1.schema_id
|
|
778
|
+
action.description.should =~ /rename field 'title' to 'a'/i
|
|
779
|
+
action = @modification.actions[2]
|
|
780
|
+
action.action.should == :rename
|
|
781
|
+
action.source.should == @df1.schema_id
|
|
782
|
+
action.description.should =~ /rename field 'title' to 'b'/i
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
should "enable fixing the problem by deleting field from schema" do
|
|
786
|
+
action = @modification.actions[0]
|
|
787
|
+
begin
|
|
788
|
+
S::Schema.apply(action)
|
|
789
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
790
|
+
flunk("Deletion of field should have resolved schema error")
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
m = YAML.load_file(@map_file)
|
|
794
|
+
m.key?(@uid).should be_false
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
should "enable fixing the problem by renaming field 'a'" do
|
|
798
|
+
action = @modification.actions[1]
|
|
799
|
+
begin
|
|
800
|
+
S::Schema.apply(action)
|
|
801
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
802
|
+
flunk("Renaming of field should have resolved schema error")
|
|
803
|
+
end
|
|
804
|
+
m = YAML.load_file(@map_file)
|
|
805
|
+
m[@uid].should == @af1.schema_name
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
should "enable fixing the problem by renaming field 'b'" do
|
|
809
|
+
action = @modification.actions[2]
|
|
810
|
+
begin
|
|
811
|
+
S::Schema.apply(action)
|
|
812
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
813
|
+
flunk("Renaming of field should have resolved schema error")
|
|
814
|
+
end
|
|
815
|
+
m = YAML.load_file(@map_file)
|
|
816
|
+
m[@uid].should == @af2.schema_name
|
|
817
|
+
end
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
context "with two fields removed" do
|
|
821
|
+
setup do
|
|
822
|
+
A.field :a
|
|
823
|
+
A.field :b
|
|
824
|
+
A.field :c
|
|
825
|
+
@df1 = A.field_prototypes[:title]
|
|
826
|
+
@df2 = A.field_prototypes[:introduction]
|
|
827
|
+
@af1 = A.field_prototypes[:a]
|
|
828
|
+
@af2 = A.field_prototypes[:b]
|
|
829
|
+
@af3 = A.field_prototypes[:c]
|
|
830
|
+
@uid1 = @df1.schema_id.to_s
|
|
831
|
+
@uid2 = @df2.schema_id.to_s
|
|
832
|
+
A.stubs(:field_prototypes).returns({:a => @af1, :b => @af2, :c => @af3})
|
|
833
|
+
A.stubs(:fields).returns([@af1, @af2, @af3])
|
|
834
|
+
S::Schema.reload!
|
|
835
|
+
begin
|
|
836
|
+
S::Schema.validate!
|
|
837
|
+
flunk("Validation should raise error when adding & deleting fields")
|
|
838
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
839
|
+
@modification = e.modification
|
|
840
|
+
end
|
|
841
|
+
end
|
|
842
|
+
should "return list of solutions" do
|
|
843
|
+
# add :a, :b; delete :title, :introduction
|
|
844
|
+
# rename :title => :a, :introduction => :b
|
|
845
|
+
# rename :introduction => :a, :title => :b
|
|
846
|
+
# add :a; delete :introduction; rename :title => :b
|
|
847
|
+
# add :a; delete :title; rename :introduction => :b
|
|
848
|
+
# add :b; delete :introduction; rename :title => :a
|
|
849
|
+
# add :b; delete :title; rename :introduction => :a
|
|
850
|
+
@modification.actions.description.should =~ /field 'title'/
|
|
851
|
+
@modification.actions.length.should == 4
|
|
852
|
+
action = @modification.actions[0]
|
|
853
|
+
action.action.should == :delete
|
|
854
|
+
action.source.should == @df1.schema_id
|
|
855
|
+
action.description.should =~ /delete field 'title'/i
|
|
856
|
+
action = @modification.actions[1]
|
|
857
|
+
action.action.should == :rename
|
|
858
|
+
action.source.should == @df1.schema_id
|
|
859
|
+
action.description.should =~ /rename field 'title' to 'a'/i
|
|
860
|
+
action = @modification.actions[2]
|
|
861
|
+
action.action.should == :rename
|
|
862
|
+
action.source.should == @df1.schema_id
|
|
863
|
+
action.description.should =~ /rename field 'title' to 'b'/i
|
|
864
|
+
action = @modification.actions[3]
|
|
865
|
+
action.action.should == :rename
|
|
866
|
+
action.source.should == @df1.schema_id
|
|
867
|
+
action.description.should =~ /rename field 'title' to 'c'/i
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
should "enable fixing the problem by deleting both fields" do
|
|
871
|
+
action = @modification.actions[0]
|
|
872
|
+
begin
|
|
873
|
+
S::Schema.apply(action)
|
|
874
|
+
flunk("Deletion of field should not have resolved schema error")
|
|
875
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
876
|
+
modification = e.modification
|
|
877
|
+
end
|
|
878
|
+
action = modification.actions[0]
|
|
879
|
+
|
|
880
|
+
begin
|
|
881
|
+
S::Schema.apply(action)
|
|
882
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
883
|
+
flunk("Deletion of field should have resolved schema error")
|
|
884
|
+
end
|
|
885
|
+
m = YAML.load_file(@map_file)
|
|
886
|
+
m.key?(@uid1).should be_false
|
|
887
|
+
m.key?(@uid2).should be_false
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
should "enable fixing the problem by deleting one field and renaming other as 'a'" do
|
|
891
|
+
action = @modification.actions[0]
|
|
892
|
+
begin
|
|
893
|
+
S::Schema.apply(action)
|
|
894
|
+
flunk("Deletion of field should not have resolved schema error")
|
|
895
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
896
|
+
modification = e.modification
|
|
897
|
+
end
|
|
898
|
+
action = modification.actions[1]
|
|
899
|
+
|
|
900
|
+
begin
|
|
901
|
+
S::Schema.apply(action)
|
|
902
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
903
|
+
flunk("Deletion of field should have resolved schema error")
|
|
904
|
+
end
|
|
905
|
+
m = YAML.load_file(@map_file)
|
|
906
|
+
m.key?(@uid1).should be_false
|
|
907
|
+
m.key?(@uid2).should be_true
|
|
908
|
+
m[@uid2].should == @af1.schema_name
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
should "enable fixing the problem by renaming one field as 'c' and deleting other" do
|
|
912
|
+
action = @modification.actions[3]
|
|
913
|
+
begin
|
|
914
|
+
S::Schema.apply(action)
|
|
915
|
+
flunk("Renaming of field should not have resolved schema error")
|
|
916
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
917
|
+
modification = e.modification
|
|
918
|
+
end
|
|
919
|
+
action = modification.actions[0]
|
|
920
|
+
|
|
921
|
+
begin
|
|
922
|
+
S::Schema.apply(action)
|
|
923
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
924
|
+
flunk("Deletion of field should have resolved schema error")
|
|
925
|
+
end
|
|
926
|
+
m = YAML.load_file(@map_file)
|
|
927
|
+
m.key?(@uid1).should be_true
|
|
928
|
+
m.key?(@uid2).should be_false
|
|
929
|
+
m[@uid1].should == @af3.schema_name
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
should "enable fixing the problem by renaming one field as 'c' and renaming other as 'b'" do
|
|
933
|
+
action = @modification.actions[3]
|
|
934
|
+
begin
|
|
935
|
+
S::Schema.apply(action)
|
|
936
|
+
flunk("Renaming of field should not have resolved schema error")
|
|
937
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
938
|
+
modification = e.modification
|
|
939
|
+
end
|
|
940
|
+
action = modification.actions[2]
|
|
941
|
+
|
|
942
|
+
begin
|
|
943
|
+
S::Schema.apply(action)
|
|
944
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
945
|
+
flunk("Deletion of field should have resolved schema error")
|
|
946
|
+
end
|
|
947
|
+
m = YAML.load_file(@map_file)
|
|
948
|
+
m.key?(@uid1).should be_true
|
|
949
|
+
m.key?(@uid2).should be_true
|
|
950
|
+
m[@uid1].should == @af3.schema_name
|
|
951
|
+
m[@uid2].should == @af2.schema_name
|
|
952
|
+
end
|
|
953
|
+
|
|
954
|
+
context "and two boxes removed" do
|
|
955
|
+
setup do
|
|
956
|
+
@db1 = A.boxes[:posts]
|
|
957
|
+
A.box :added1
|
|
958
|
+
A.box :added2
|
|
959
|
+
@ab1 = A.boxes[:added1]
|
|
960
|
+
@ab2 = A.boxes[:added2]
|
|
961
|
+
boxes = S::Collections::PrototypeSet.new
|
|
962
|
+
boxes[:added1] = @ab1
|
|
963
|
+
boxes[:added2] = @ab2
|
|
964
|
+
A.stubs(:box_prototypes).returns(boxes)
|
|
965
|
+
classes = S::Schema.classes.dup
|
|
966
|
+
classes.delete(A::PostsBox)
|
|
967
|
+
S::Schema.stubs(:classes).returns(classes)
|
|
968
|
+
S::Schema.reload!
|
|
969
|
+
begin
|
|
970
|
+
S::Schema.validate!
|
|
971
|
+
flunk("Validation should raise error when adding & deleting fields")
|
|
972
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
973
|
+
@modification = e.modification
|
|
974
|
+
end
|
|
975
|
+
end
|
|
976
|
+
should "enable fixing by deleting both fields and renaming a box" do
|
|
977
|
+
action = @modification.actions[0]
|
|
978
|
+
begin
|
|
979
|
+
S::Schema.apply(action)
|
|
980
|
+
flunk("Deleting of field should not have resolved schema error")
|
|
981
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
982
|
+
modification = e.modification
|
|
983
|
+
end
|
|
984
|
+
action = modification.actions[0]
|
|
985
|
+
|
|
986
|
+
begin
|
|
987
|
+
S::Schema.apply(action)
|
|
988
|
+
flunk("Deleting of field should not have resolved schema error")
|
|
989
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
990
|
+
modification = e.modification
|
|
991
|
+
end
|
|
992
|
+
action = modification.actions[1]
|
|
993
|
+
|
|
994
|
+
begin
|
|
995
|
+
S::Schema.apply(action)
|
|
996
|
+
rescue Spontaneous::SchemaModificationError => e
|
|
997
|
+
flunk("Schema changes should have resolved error")
|
|
998
|
+
end
|
|
999
|
+
# p modification.actions
|
|
1000
|
+
end
|
|
1001
|
+
end
|
|
1002
|
+
end
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
end
|
|
1006
|
+
end
|
|
1007
|
+
end
|
|
1008
|
+
end
|
|
1009
|
+
|