potassium 5.2.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +42 -0
  3. data/.editorconfig +3 -0
  4. data/.node-version +1 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +94 -0
  7. data/README.md +41 -47
  8. data/docs/DSL.md +5 -5
  9. data/lib/potassium/assets/.buildpacks +0 -1
  10. data/lib/potassium/assets/.circleci/config.yml.erb +102 -0
  11. data/lib/potassium/assets/.eslintrc.json +352 -0
  12. data/lib/potassium/assets/.github/pull_request_template.md +9 -0
  13. data/lib/potassium/assets/.pryrc +1 -1
  14. data/lib/potassium/assets/.rubocop.yml +515 -0
  15. data/lib/potassium/assets/.stylelintrc.json +46 -0
  16. data/lib/potassium/assets/Dockerfile.ci +1 -1
  17. data/lib/potassium/assets/Makefile.erb +35 -0
  18. data/lib/potassium/assets/Procfile +1 -0
  19. data/lib/potassium/assets/README.yml +60 -11
  20. data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
  21. data/lib/potassium/assets/active_admin/admin_application.js +14 -0
  22. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
  23. data/lib/potassium/assets/app/graphql/graphql_controller.rb +55 -0
  24. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +23 -0
  25. data/lib/potassium/assets/app/graphql/queries/base_query.rb +4 -0
  26. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +4 -0
  27. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +4 -0
  28. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +5 -0
  29. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +5 -0
  30. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +7 -0
  31. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +5 -0
  32. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +4 -0
  33. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +4 -0
  34. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +10 -0
  35. data/lib/potassium/assets/app/graphql/types/query_type.rb +13 -0
  36. data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
  37. data/lib/potassium/assets/app/uploaders/base_uploader.rb +11 -0
  38. data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
  39. data/lib/potassium/assets/bin/cibuild.erb +24 -7
  40. data/lib/potassium/assets/bin/release +9 -0
  41. data/lib/potassium/assets/bin/setup.erb +3 -0
  42. data/lib/potassium/assets/config/database_mysql.yml.erb +5 -5
  43. data/lib/potassium/assets/config/database_postgresql.yml.erb +5 -5
  44. data/lib/potassium/assets/config/graphql_playground.rb +20 -0
  45. data/lib/potassium/assets/config/puma.rb +5 -1
  46. data/lib/potassium/assets/config/shrine.rb +36 -0
  47. data/lib/potassium/assets/docker-compose.ci.yml +2 -1
  48. data/lib/potassium/assets/docker-compose.yml +6 -0
  49. data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +34 -33
  50. data/lib/potassium/assets/package.json +4 -1
  51. data/lib/potassium/assets/redis.yml +1 -2
  52. data/lib/potassium/assets/sidekiq_scheduler.yml +1 -1
  53. data/lib/potassium/assets/testing/rails_helper.rb +4 -2
  54. data/lib/potassium/cli/commands/create.rb +12 -19
  55. data/lib/potassium/cli_options.rb +67 -24
  56. data/lib/potassium/helpers/docker-helpers.rb +14 -5
  57. data/lib/potassium/helpers/gem-helpers.rb +1 -1
  58. data/lib/potassium/helpers/template-helpers.rb +4 -0
  59. data/lib/potassium/newest_version_ensurer.rb +19 -36
  60. data/lib/potassium/node_version_ensurer.rb +30 -0
  61. data/lib/potassium/recipes/admin.rb +3 -3
  62. data/lib/potassium/recipes/annotate.rb +1 -1
  63. data/lib/potassium/recipes/api.rb +93 -21
  64. data/lib/potassium/recipes/background_processor.rb +38 -2
  65. data/lib/potassium/recipes/ci.rb +8 -6
  66. data/lib/potassium/recipes/data_migrate.rb +44 -0
  67. data/lib/potassium/recipes/database.rb +6 -2
  68. data/lib/potassium/recipes/database_container.rb +90 -0
  69. data/lib/potassium/recipes/draper.rb +1 -10
  70. data/lib/potassium/recipes/file_storage.rb +66 -0
  71. data/lib/potassium/recipes/front_end.rb +219 -9
  72. data/lib/potassium/recipes/github.rb +93 -15
  73. data/lib/potassium/recipes/heroku.rb +2 -1
  74. data/lib/potassium/recipes/listen.rb +7 -0
  75. data/lib/potassium/recipes/mailer.rb +14 -4
  76. data/lib/potassium/recipes/node.rb +21 -0
  77. data/lib/potassium/recipes/puma.rb +0 -3
  78. data/lib/potassium/recipes/rack_cors.rb +18 -15
  79. data/lib/potassium/recipes/rails.rb +6 -0
  80. data/lib/potassium/recipes/schedule.rb +1 -1
  81. data/lib/potassium/recipes/style.rb +21 -3
  82. data/lib/potassium/recipes/vue_admin.rb +124 -0
  83. data/lib/potassium/templates/application.rb +10 -9
  84. data/lib/potassium/version.rb +7 -4
  85. data/potassium.gemspec +9 -6
  86. data/spec/features/api_spec.rb +25 -0
  87. data/spec/features/background_processor_spec.rb +12 -1
  88. data/spec/features/data_migrate_spec.rb +14 -0
  89. data/spec/features/database_container_spec.rb +35 -0
  90. data/spec/features/draper_spec.rb +1 -6
  91. data/spec/features/file_storage_spec.rb +75 -0
  92. data/spec/features/front_end_spec.rb +88 -0
  93. data/spec/features/github_spec.rb +53 -8
  94. data/spec/features/graphql_spec.rb +71 -0
  95. data/spec/features/heroku_spec.rb +8 -5
  96. data/spec/features/mailer_spec.rb +42 -0
  97. data/spec/features/new_project_spec.rb +6 -14
  98. data/spec/features/node_spec.rb +28 -0
  99. data/spec/features/power_types_spec.rb +5 -16
  100. data/spec/features/vue_admin_spec.rb +47 -0
  101. data/spec/spec_helper.rb +5 -0
  102. data/spec/support/fake_octokit.rb +31 -0
  103. data/spec/support/potassium_test_helpers.rb +26 -8
  104. metadata +126 -45
  105. data/circle.yml +0 -12
  106. data/lib/potassium/assets/.circleci/config.yml +0 -20
  107. data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
  108. data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
  109. data/lib/potassium/assets/api/api_error_concern.rb +0 -32
  110. data/lib/potassium/assets/api/base_controller.rb +0 -9
  111. data/lib/potassium/assets/api/draper_responder.rb +0 -62
  112. data/lib/potassium/assets/api/responder.rb +0 -41
  113. data/lib/potassium/assets/aws.rb +0 -1
  114. data/lib/potassium/assets/testing/paperclip.rb +0 -59
  115. data/lib/potassium/recipes/active_storage.rb +0 -40
  116. data/lib/potassium/recipes/angular_admin.rb +0 -56
  117. data/lib/potassium/recipes/aws_sdk.rb +0 -7
  118. data/lib/potassium/recipes/paperclip.rb +0 -47
  119. data/spec/features/active_storage_spec.rb +0 -30
  120. data/spec/features/front_end.rb +0 -30
@@ -0,0 +1,46 @@
1
+ {
2
+ "rules": {
3
+ "declaration-bang-space-before": "always",
4
+ "declaration-bang-space-after": "never",
5
+ "declaration-property-value-blacklist": {
6
+ "/^border/": ["none"]
7
+ },
8
+ "color-named": "never",
9
+ "declaration-block-no-duplicate-properties": true,
10
+ "rule-empty-line-before": ["always-multi-line", {
11
+ "except": ["after-single-line-comment", "first-nested"]
12
+ }],
13
+ "block-no-empty": true,
14
+ "no-missing-end-of-source-newline": true,
15
+ "color-hex-length": "short",
16
+ "color-hex-case": "lower",
17
+ "color-no-invalid-hex": true,
18
+ "selector-max-id": 0,
19
+ "declaration-no-important": true,
20
+ "indentation": 2,
21
+ "number-leading-zero": "never",
22
+ "no-duplicate-selectors": true,
23
+ "max-nesting-depth": 3,
24
+ "selector-pseudo-element-colon-notation": "double",
25
+ "selector-no-qualifying-type": true,
26
+ "shorthand-property-no-redundant-values": true,
27
+ "declaration-block-semicolon-newline-after": "always-multi-line",
28
+ "selector-list-comma-newline-after": "always",
29
+ "function-comma-space-after": "always-single-line",
30
+ "declaration-colon-space-after": "always",
31
+ "declaration-colon-space-before": "never",
32
+ "block-opening-brace-space-before": "always",
33
+ "function-parentheses-space-inside": "never",
34
+ "string-quotes": "single",
35
+ "declaration-block-trailing-semicolon": "always",
36
+ "no-eol-whitespace": true,
37
+ "number-no-trailing-zeros": true,
38
+ "function-url-quotes": "always",
39
+ "property-no-vendor-prefix": true,
40
+ "selector-no-vendor-prefix": true,
41
+ "media-feature-name-no-vendor-prefix": true,
42
+ "at-rule-no-vendor-prefix": true,
43
+ "value-no-vendor-prefix": true,
44
+ "length-zero-no-unit": true
45
+ }
46
+ }
@@ -1,4 +1,4 @@
1
- FROM platanus/ruby:2.5
1
+ FROM platanus/ruby:2.7
2
2
 
3
3
  RUN mkdir /app
4
4
  WORKDIR /app
@@ -0,0 +1,35 @@
1
+ PROJECT ?= <%= get(:dasherized_app_name) %>
2
+
3
+ SHELL := /bin/bash
4
+
5
+ run: help
6
+
7
+ BOLD ?= $(shell tput bold)
8
+ NORMAL ?= $(shell tput sgr0)
9
+
10
+ help:
11
+ @echo "Generate a backup in the environment (staging|production) database:"
12
+ @echo " ${BOLD}make backup-<environment>${NORMAL}"
13
+ @echo ""
14
+ @echo "Copy latest database backup from the environment (staging|production) to local database:"
15
+ @echo " ${BOLD}make restore-from-<environment>${NORMAL}"
16
+ @echo ""
17
+
18
+ services-port:
19
+ @set -o pipefail; \
20
+ docker-compose port ${SERVICE} ${PORT} 2> /dev/null | cut -d':' -f2 || echo ${PORT}
21
+
22
+ backup-staging: ROLE=staging
23
+ backup-production: ROLE=production
24
+ backup-%:
25
+ @echo Capturing $(ROLE)....
26
+ @heroku pg:backups:capture --remote $(ROLE)
27
+
28
+ restore-from-staging: ROLE=staging
29
+ restore-from-production: ROLE=production
30
+ restore-from-%:
31
+ $(eval TEMP_FILE=$(shell mktemp))
32
+ @echo Restoring from $(ROLE)....
33
+ @heroku pg:backups:download --remote $(ROLE) --output $(TEMP_FILE)
34
+ @pg_restore --verbose --clean --no-acl --no-owner -h localhost \
35
+ -U postgres -p $(shell make services-port SERVICE=postgresql PORT=5432) -d $(PROJECT)_development $(TEMP_FILE)
@@ -1 +1,2 @@
1
1
  web: bundle exec puma -C ./config/puma.rb
2
+ release: bin/release
@@ -8,12 +8,12 @@ readme:
8
8
 
9
9
  $ ./bin/setup
10
10
 
11
- It assumes you have a machine equipped with Ruby, <%= get(:database).to_s.titleize %>, etc. If not, set up
12
- your machine with [boxen].
11
+ It assumes you have a machine equipped with Ruby, Node.js, Docker and make.
13
12
 
14
13
  The script will do the following among other things:
15
14
 
16
15
  - Install the dependecies
16
+ - Create a docker container for your database
17
17
  - Prepare your database
18
18
  - Adds heroku remotes
19
19
 
@@ -22,7 +22,20 @@ readme:
22
22
  $ heroku local
23
23
 
24
24
  [Heroku Local]: https://devcenter.heroku.com/articles/heroku-local
25
- [boxen]: http://github.com/platanus/our-boxen
25
+ webpack:
26
+ title: "Development"
27
+ body: |
28
+ For hot-reloading and fast webpacker compilation you need to run webpack's dev server along with the rails server:
29
+
30
+ $ ./bin/webpack-dev-server
31
+
32
+ Running the dev server will also solve problems with the cache not refreshing between changes and provide better error messages if something fails to compile.
33
+
34
+ For even faster in-place component refreshing (with no page reloads), you can enable Hot Module Reloading in `config/webpacker.yml`
35
+
36
+ development:
37
+ dev_server:
38
+ hmr: true
26
39
  ci:
27
40
  title: "Continuous Integrations"
28
41
  body: |
@@ -62,10 +75,17 @@ readme:
62
75
  style_guide:
63
76
  title: "Style Guides"
64
77
  body: |
65
- The style guides are enforced through a self hosted version of [Hound CI](http://monkeyci.platan.us). The style configuration can also be used locally
66
- in development runing `rubocop` or just using the rubocop integration for your text editor of choice.
78
+ Style guides are enforced through a CircleCI [job](.circleci/config.yml) with [reviewdog](https://github.com/reviewdog/reviewdog) as a reporter, using per-project dependencies and style configurations.
79
+ Please note that this reviewdog implementation requires a GitHub user token to comment on pull requests. A token can be generated [here](https://github.com/settings/tokens), and it should have at least the `repo` option checked.
80
+ The included `config.yml` assumes your CircleCI organization has a context named `org-global` with the required token under the environment variable `REVIEWDOG_GITHUB_API_TOKEN`.
81
+
82
+ The project comes bundled with configuration files available in this repository.
83
+
84
+ Linting dependencies like `rubocop` or `rubocop-rspec` must be locked in your `Gemfile`. Similarly, packages like `eslint` or `eslint-plugin-vue` must be locked in your `package.json`.
85
+
86
+ You can add or modify rules by editing the [`.rubocop.yml`](.rubocop.yml), [`.eslintrc.json`](.eslintrc.json) or [`.stylelintrc.json`](.stylelintrc.json) files.
67
87
 
68
- You can add custom rules to this project just adding them to the `.ruby-style.yml` file.
88
+ You can (and should) use linter integrations for your text editor of choice, using the project's configuration.
69
89
  mailing:
70
90
  title: "Sending Emails"
71
91
  body: |
@@ -83,12 +103,12 @@ readme:
83
103
  devise:
84
104
  title: "Authentication"
85
105
  body: "We are using the great [Devise](https://github.com/plataformatec/devise) library by [PlataformaTec](http://plataformatec.com.br/)"
86
- paperclip:
87
- title: "Uploads"
88
- body: "For managing uploads, this project uses [Paperclip](https://github.com/thoughtbot/paperclip), a gem made by the awesome [Thoughbot](https://thoughtbot.com/) team."
89
- storage:
90
- title: "Active Storage"
106
+ active_storage:
107
+ title: "File Storage"
91
108
  body: "For managing uploads, this project uses [Active Storage](https://github.com/rails/rails/tree/master/activestorage)."
109
+ shrine:
110
+ title: "File Storage"
111
+ body: "For managing uploads, this project uses [Shrine](https://github.com/shrinerb/shrine)."
92
112
  pundit:
93
113
  title: "Authorization"
94
114
  body: "For defining which parts of the system each user has access to, we have chosen to include the [Pundit](https://github.com/elabs/pundit) gem, by [Elabs](http://elabs.se/)."
@@ -110,6 +130,35 @@ readme:
110
130
  power_types:
111
131
  title: "Rails pattern enforcing types"
112
132
  body: "This projects uses [Power-Types](https://github.com/platanus/power-types) to generate Services, Commands, Utils and Values."
133
+ power_api:
134
+ title: "API Support"
135
+ body: "This projects uses [Power API](https://github.com/platanus/power_api). It's a Rails engine that gathers a set of gems and configurations designed to build incredible REST APIs."
136
+ graphql:
137
+ title: "API Support"
138
+ body: "This projects uses [graphql-ruby](https://graphql-ruby.org/) to generate a GraphQL API."
139
+ active_admin:
140
+ title: "Administration"
141
+ body: |
142
+ This project uses [Active Admin](https://github.com/activeadmin/activeadmin) which is a Ruby on Rails framework for creating elegant backends for website administration.
143
+ <% if get(:vue_admin) %>
144
+ This project supports Vue inside ActiveAdmin
145
+ - The main package is located in `app/javascript/packs/admin_application.js`, here you will declare the components you want to include in your ActiveAdmin views as you would in a normal Vue App.
146
+ - Additionally, to be able to use Vue components as [Arbre](https://github.com/activeadmin/arbre) Nodes the component names are also declared in `config/initializers/active_admin.rb`
147
+ - The generator includes an example component called `admin_component`, you can use this component inside any ActiveAdmin view by just writing `admin_component` as you would with any `html` tag.
148
+ - For example:
149
+ ```
150
+ admin_component(class:"myCustomClass",id:"myCustomId") do
151
+ admin_component(id:"otherCustomId")
152
+ end
153
+ ```
154
+ - (Keep in mind that the example works with ruby blocks because `AdminComponent` has a `<slot>` tag defined, therefore children can be added to the component)
155
+ - The integration supports passing props to the components and converts them to their corresponing javascript objects.
156
+ - For example, the following works
157
+ ```
158
+ admin_component(testList:[1,2,3,4],testObject:{"name":"Vue component"})
159
+ ```
160
+ - You can also use **any** vue bindings such as `v-for` , `:key` etc.
161
+ <% end %>
113
162
  seeds:
114
163
  title: "Seeds"
115
164
  body: |
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <div>
3
+ I am a Vue Component {{ test }} {{ message }}
4
+ <slot />
5
+ </div>
6
+ </template>
7
+
8
+ <script>
9
+ export default {
10
+ props: {
11
+ test: {
12
+ type: String,
13
+ default: '',
14
+ },
15
+ testNumber: {
16
+ type: Number,
17
+ default: 0,
18
+ },
19
+ testObject: {
20
+ type: Object,
21
+ default: null,
22
+ },
23
+ testList: {
24
+ type: Array,
25
+ default: null,
26
+ },
27
+ },
28
+
29
+ data() {
30
+ return {
31
+ message: 'Hello World',
32
+ };
33
+ },
34
+ };
35
+ </script>
@@ -0,0 +1,14 @@
1
+ import Vue from 'vue/dist/vue.esm';
2
+ import AdminComponent from '../components/admin-component';
3
+
4
+ Vue.component('admin_component', AdminComponent);
5
+
6
+ document.addEventListener('DOMContentLoaded', () => {
7
+ if (document.getElementById('wrapper') !== null) {
8
+ return new Vue({
9
+ el: '#wrapper',
10
+ });
11
+ }
12
+
13
+ return null;
14
+ });
@@ -0,0 +1,10 @@
1
+ module AdminPageLayoutOverride
2
+ def build_page(*args)
3
+ within head do
4
+ text_node(javascript_packs_with_chunks_tag('admin_application'))
5
+ end
6
+ super
7
+ end
8
+ end
9
+
10
+ ActiveAdmin::Views::Pages::Base.send :prepend, AdminPageLayoutOverride
@@ -0,0 +1,55 @@
1
+ class GraphqlController < ApplicationController
2
+ # If accessing from outside this domain, nullify the session
3
+ # This allows for outside API access while preventing CSRF attacks,
4
+ # but you'll have to authenticate your user separately
5
+ # protect_from_forgery with: :null_session
6
+
7
+ def execute
8
+ variables = prepare_variables(params[:variables])
9
+ query = params[:query]
10
+ operation_name = params[:operationName]
11
+ context = { current_user: get_current_user }
12
+ result = GqlSampleSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
13
+ render json: result
14
+ rescue => e
15
+ raise e unless Rails.env.development?
16
+ handle_error_in_development e
17
+ end
18
+
19
+ private
20
+
21
+ # Handle variables in form data, JSON body, or a blank value
22
+ def prepare_variables(variables_param)
23
+ case variables_param
24
+ when String
25
+ if variables_param.present?
26
+ JSON.parse(variables_param) || {}
27
+ else
28
+ {}
29
+ end
30
+ when Hash
31
+ variables_param
32
+ when ActionController::Parameters
33
+ variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
34
+ when nil
35
+ {}
36
+ else
37
+ raise ArgumentError, "Unexpected parameter: #{variables_param}"
38
+ end
39
+ end
40
+
41
+ def handle_error_in_development(e)
42
+ logger.error e.message
43
+ logger.error e.backtrace.join("\n")
44
+
45
+ render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: 500
46
+ end
47
+
48
+ def get_current_user
49
+ if request.headers['Authorization']
50
+ _, token = request.headers['Authorization'].split
51
+ decoded_token = JWT.decode token, ENV['HMAC_SECRET'], true, { algorithm: 'HS256' }
52
+ User.find(decoded_token.first["id"])
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,23 @@
1
+ require 'jwt'
2
+
3
+ class Mutations::LoginMutation < Mutations::BaseMutation
4
+ null true
5
+
6
+ argument :email, String, required: true
7
+ argument :password, String, required: true
8
+
9
+
10
+ field :token, String, null: true
11
+
12
+ def resolve(email:, password:)
13
+ user = User.find_by(email: email)
14
+ if user&.valid_password?(password)
15
+ payload = { id: user.id, email: user.email, exp: (Time.zone.now + 24.hours).to_i }
16
+ token = JWT.encode payload, ENV['HMAC_SECRET'], 'HS256'
17
+ return { token: token }
18
+ end
19
+ GraphQL::ExecutionError.new("User or Password invalid")
20
+ rescue ActiveRecord::RecordInvalid => e
21
+ GraphQL::ExecutionError.new("Invalid input: #{e.record.errors.full_messages.join(', ')}")
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ module Queries
2
+ class BaseQuery < GraphQL::Schema::Resolver
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Types::Base
2
+ class BaseArgument < GraphQL::Schema::Argument
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Types::Base
2
+ class BaseEnum < GraphQL::Schema::Enum
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module Types::Base
2
+ class BaseField < GraphQL::Schema::Field
3
+ argument_class Types::Base::BaseArgument
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Types::Base
2
+ class BaseInputObject < GraphQL::Schema::InputObject
3
+ argument_class Types::Base::BaseArgument
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Types::Base
2
+ module BaseInterface
3
+ include GraphQL::Schema::Interface
4
+
5
+ field_class Types::Base::BaseField
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Types::Base
2
+ class BaseObject < GraphQL::Schema::Object
3
+ field_class Types::Base::BaseField
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Types::Base
2
+ class BaseScalar < GraphQL::Schema::Scalar
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Types::Base
2
+ class BaseUnion < GraphQL::Schema::Union
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module Types
2
+ class MutationType < Types::Base::BaseObject
3
+ # TODO: remove me
4
+ field :test_field, String, null: false,
5
+ description: "An example field added by the generator"
6
+ def test_field
7
+ "Hello World"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Types
2
+ class QueryType < Types::Base::BaseObject
3
+ # Add root-level fields here.
4
+ # They will be entry points for queries on your schema.
5
+
6
+ # TODO: remove me
7
+ field :test_field, String, null: false,
8
+ description: "An example field added by the generator"
9
+ def test_field
10
+ "Hello World!"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import App from 'app';
3
+
4
+ describe('App', () => {
5
+ test('is a Vue instance', () => {
6
+ const wrapper = shallowMount(App);
7
+ expect(wrapper.isVueInstance()).toBeTruthy();
8
+ });
9
+
10
+ it('displays message on load', () => {
11
+ const wrapper = shallowMount(App);
12
+ expect(wrapper.find('p').text()).toEqual('Hello Vue!');
13
+ });
14
+ });