diff --git a/.erdconfig b/.erdconfig new file mode 100644 index 0000000..d6330e4 --- /dev/null +++ b/.erdconfig @@ -0,0 +1,11 @@ +filetype: svg +orientation: vertical +attributes: + - content + - foreign_key + - inheritance +exclude: + - ActiveRecord::InternalMetadata + - ActiveRecord::SchemaMigration + - primary::SchemaMigration + - Audited::Audit diff --git a/.eslintrc b/.eslintrc index 7f775ba..bea5ba5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": ["vtex"], + "extends": ["vtex", "plugin:relay/recommended"], "ignorePatterns": [ "__mocks__/", "__generated__/" @@ -9,5 +9,9 @@ "files": ["**/*.tsx"], "extends": ["vtex-react"] } - ] + ], + "rules": { + "relay/generated-flow-types": "false" + }, + "plugins": ["relay"] } diff --git a/Gemfile b/Gemfile index 4801de5..404f3e8 100644 --- a/Gemfile +++ b/Gemfile @@ -28,8 +28,11 @@ gem "pundit" group :development, :test do gem "dotenv-rails" gem "pry-byebug", platforms: [:mri, :mingw, :x64_mingw] - gem "capybara" + gem "rails-erd" + gem "rspec-rails" + gem "faker", "~> 2.18" + gem "factory_bot_rails", "~> 6.2" gem "rubocop-rails", require: false gem "rubocop-rspec", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 38f8401..fc32f9f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,8 +60,6 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) administrate (0.16.0) actionpack (>= 5.0) actionview (>= 5.0) @@ -85,14 +83,7 @@ GEM msgpack (~> 1.0) builder (3.2.4) byebug (11.1.3) - capybara (3.35.3) - addressable - mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (>= 1.5, < 3.0) - xpath (~> 3.2) + choice (0.2.0) coderay (1.1.3) concurrent-ruby (1.1.9) crass (1.0.6) @@ -114,6 +105,13 @@ GEM enumerize (2.4.0) activesupport (>= 3.2) erubi (1.10.0) + factory_bot (6.2.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faker (2.18.0) + i18n (>= 1.6, < 2) ffi (1.15.3) globalid (0.5.2) activesupport (>= 5.0) @@ -182,7 +180,6 @@ GEM pry-byebug (3.9.0) byebug (~> 11.0) pry (~> 0.13.0) - public_suffix (4.0.6) puma (5.4.0) nio4r (~> 2.0) pundit (2.1.0) @@ -211,6 +208,11 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) + rails-erd (1.6.1) + activerecord (>= 4.2) + activesupport (>= 4.2) + choice (~> 0.2.0) + ruby-graphviz (~> 1.2) rails-html-sanitizer (1.3.0) loofah (~> 2.3) railties (6.1.4) @@ -268,6 +270,8 @@ GEM rubocop-ast (>= 1.1.0) rubocop-shopify (2.2.0) rubocop (~> 1.18) + ruby-graphviz (1.2.5) + rexml ruby-progressbar (1.11.0) ruby-vips (2.1.2) ffi (~> 1.12) @@ -318,8 +322,6 @@ GEM websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) zeitwerk (2.4.2) PLATFORMS @@ -330,11 +332,12 @@ DEPENDENCIES administrate-field-active_storage annotate bootsnap (>= 1.4.4) - capybara devise devise-i18n dotenv-rails enumerize + factory_bot_rails (~> 6.2) + faker (~> 2.18) graphql graphql_playground-rails image_processing (~> 1.12) @@ -345,6 +348,7 @@ DEPENDENCIES puma (~> 5.0) pundit rails (~> 6.1.4) + rails-erd rspec-graphql_matchers (~> 1.3) rspec-rails rubocop-rails diff --git a/README.md b/README.md index 12cdd6d..da28abd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ * Postgres 13.x * [Watchman](https://github.com/facebook/watchman) (opcional) - ## 🚀 Instalando Comandos para a instalação: @@ -42,3 +41,6 @@ yarn relay ``` yarn relay:watch // requer a instalação do watchman ``` + +## ⛳ Modelo De DomÃnio + diff --git a/app/graphql/inputs/user_attributes_input.rb b/app/graphql/inputs/user_attributes_input.rb deleted file mode 100644 index 61dc56a..0000000 --- a/app/graphql/inputs/user_attributes_input.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true -module Inputs - class UserAttributesInput < Types::BaseInputObject - graphql_name "UserAttributesInput" - - argument :first_name, String, required: true - argument :last_name, String, required: true - end -end diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index daacf47..c945e2f 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -39,6 +39,36 @@ type Currency implements Node { name: String! } +""" +The connection type for Currency. +""" +type CurrencyConnection { + """ + A list of edges. + """ + edges: [CurrencyEdge!]! + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CurrencyEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: Currency! +} + type FiatBalance implements Node { amountCents: Int! amountCurrency: String! @@ -139,6 +169,27 @@ type Query { """ last: Int ): BalanceConnection! + currencies( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CurrencyConnection! currentUser: User fiatBalances( """ diff --git a/app/javascript/src/Routes.tsx b/app/javascript/src/Routes.tsx index b429084..de22071 100644 --- a/app/javascript/src/Routes.tsx +++ b/app/javascript/src/Routes.tsx @@ -2,7 +2,7 @@ import type { FC } from "react"; import React from "react"; import { Switch, Route } from "react-router-dom"; -import { Home, Wallet } from "./pages"; +import { Home, Orders, Wallet } from "./pages"; export const Routes: FC = () => { return ( @@ -13,6 +13,9 @@ export const Routes: FC = () => { + + + ); }; diff --git a/app/javascript/src/components/SideNav.tsx b/app/javascript/src/components/SideNav.tsx index 2cfc4b9..0917cb6 100644 --- a/app/javascript/src/components/SideNav.tsx +++ b/app/javascript/src/components/SideNav.tsx @@ -18,6 +18,10 @@ const MenuItems: MenuItem[] = [ label: "Carteira", path: "/wallet", }, + { + label: "Ordem de Troca", + path: "/orders/exchange", + }, ]; export const SideNav = () => { diff --git a/app/javascript/src/pages/Orders/Exchange/Exchange.tsx b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx new file mode 100644 index 0000000..296128b --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/Exchange.tsx @@ -0,0 +1,176 @@ +import React, { useState } from "react"; +import type { FC } from "react"; +import { graphql } from "babel-plugin-relay/macro"; +import { useLazyLoadQuery } from "react-relay"; +import { BigNumber } from "bignumber.js"; +import cx from "classnames"; + +import { useCurrentUser } from "../../../contexts/UserProvider"; +import { Unauthenticated } from "../../../messages/Unauthenticated"; +import type { ExchangeQuery } from "./__generated__/ExchangeQuery.graphql"; + +const tabBaseStyles = + "w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500"; + +const selectedTabStyles = + "bg-blue-600 hover:bg-blue-700 rounded-l-frounded-full text-white"; + +const inputBaseStyles = + "rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3"; + +export const Exchange: FC = () => { + const { isAuthenticated } = useCurrentUser(); + const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY"); + const [cryptoDock, setCryptoDock] = useState("0"); + const [fiatDock, setFiatDock] = useState("0.00"); + + const { balances, fiatBalances } = useLazyLoadQuery( + graphql` + query ExchangeQuery { + fiatBalances { + edges { + node { + amountCents + } + } + } + balances { + edges { + node { + amount + } + } + } + } + `, + {} + ); + + if (!isAuthenticated) return ; + const [crypto] = balances.edges; + const [fiat] = fiatBalances.edges; + + const avaliableCrypto = new BigNumber(crypto.node.amount); + const avaliableFiat = ( + fiat.node.amountCents ? fiat.node.amountCents / 100 : 0 + ).toFixed(2); + + const handleSellTabClick = () => { + setExchangeOption("SELL"); + setCryptoDock("0"); + }; + + const handleBuyTabClick = () => { + setExchangeOption("BUY"); + setCryptoDock("0"); + }; + + const handleCryptoAmountChange = ({ + currentTarget: { value }, + }: React.ChangeEvent) => { + const newCryptoAmount = new BigNumber(value); + + if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) { + setCryptoDock(value); + } + }; + + const handleFiatAmountChange = ({ + currentTarget: { value }, + }: React.ChangeEvent) => { + const newFiatAmount = Number(value); + + if (Number(avaliableFiat) >= newFiatAmount) { + setFiatDock(value); + } + }; + + const handleMaxFiatDockButton = () => { + setFiatDock(avaliableFiat); + }; + + const handleMaxCryptoButton = () => { + setCryptoDock(avaliableCrypto.toString()); + }; + + return ( + + + + + Comprar + + + Vender + + + + + {exchangeOption === "SELL" ? "CAKE" : "BRL"} disponÃvel:{" "} + {exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat} + + + {exchangeOption === "BUY" ? ( + <> + + + Max + + > + ) : ( + <> + + + Max + + > + )} + + + + {exchangeOption === "BUY" ? "Comprar" : "Vender"} CAKE + + + + + ); +}; diff --git a/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts new file mode 100644 index 0000000..bab9853 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/__generated__/ExchangeQuery.graphql.ts @@ -0,0 +1,241 @@ +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from "relay-runtime"; +export type ExchangeQueryVariables = {}; +export type ExchangeQueryResponse = { + readonly fiatBalances: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly amountCents: number; + }; + }>; + }; + readonly balances: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly amount: string; + }; + }>; + }; +}; +export type ExchangeQuery = { + readonly response: ExchangeQueryResponse; + readonly variables: ExchangeQueryVariables; +}; + + + +/* +query ExchangeQuery { + fiatBalances { + edges { + node { + amountCents + id + } + } + } + balances { + edges { + node { + amount + id + } + } + } +} +*/ + +const node: ConcreteRequest = (function(){ +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "amountCents", + "storageKey": null +}, +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "amount", + "storageKey": null +}, +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ExchangeQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceConnection", + "kind": "LinkedField", + "name": "fiatBalances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "BalanceConnection", + "kind": "LinkedField", + "name": "balances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "BalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Balance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "ExchangeQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceConnection", + "kind": "LinkedField", + "name": "fiatBalances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FiatBalance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/), + (v2/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "BalanceConnection", + "kind": "LinkedField", + "name": "balances", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "BalanceEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Balance", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/), + (v2/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "bb1b8283beba2daf38bacec716816383", + "id": null, + "metadata": {}, + "name": "ExchangeQuery", + "operationKind": "query", + "text": "query ExchangeQuery {\n fiatBalances {\n edges {\n node {\n amountCents\n id\n }\n }\n }\n balances {\n edges {\n node {\n amount\n id\n }\n }\n }\n}\n" + } +}; +})(); +(node as any).hash = '517d3bf7bc6330021f8eb615e78417f5'; +export default node; diff --git a/app/javascript/src/pages/Orders/Exchange/index.ts b/app/javascript/src/pages/Orders/Exchange/index.ts new file mode 100644 index 0000000..9196238 --- /dev/null +++ b/app/javascript/src/pages/Orders/Exchange/index.ts @@ -0,0 +1 @@ +export * from "./Exchange"; diff --git a/app/javascript/src/pages/Orders/index.ts b/app/javascript/src/pages/Orders/index.ts new file mode 100644 index 0000000..5824f1b --- /dev/null +++ b/app/javascript/src/pages/Orders/index.ts @@ -0,0 +1,5 @@ +import { Exchange } from "./Exchange"; + +export const Orders = { + Exchange, +}; diff --git a/app/javascript/src/pages/index.ts b/app/javascript/src/pages/index.ts index f07c67e..e00ff4d 100644 --- a/app/javascript/src/pages/index.ts +++ b/app/javascript/src/pages/index.ts @@ -1,2 +1,3 @@ export * from "./Home"; export * from "./Wallet"; +export * from "./Orders"; diff --git a/app/models/user.rb b/app/models/user.rb index 26d827a..cbc1d8d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,7 +25,7 @@ class User < ApplicationRecord :recoverable, :rememberable, :validatable has_many :documents, class_name: "UserDocument", dependent: :destroy - has_many :balances, dependent: :restrict_with_error + has_one :balance, dependent: :restrict_with_error has_one :fiat_balance, dependent: :restrict_with_error validates :first_name, :last_name, :email, presence: true diff --git a/db/migrate/20210812011039_create_fiat_balances.rb b/db/migrate/20210812011039_create_fiat_balances.rb index d139f0a..285df7c 100644 --- a/db/migrate/20210812011039_create_fiat_balances.rb +++ b/db/migrate/20210812011039_create_fiat_balances.rb @@ -3,7 +3,9 @@ class CreateFiatBalances < ActiveRecord::Migration[6.1] def change create_table(:fiat_balances) do |t| t.references(:user, null: false, foreign_key: true) - t.monetize(:amount) + + t.integer(:amount_cents, null: false, default: 0) + t.string(:amount_currency, null: false, default: "BRL") t.timestamps end diff --git a/db/seeds.rb b/db/seeds.rb index f04c278..092f13f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -17,4 +17,4 @@ Balance.create!( amount: (rand * (10000 - 0) + 0) ) -FiatBalance.create!(user_id: user.id) +FiatBalance.create!(user_id: user.id, amount_cents: 15000) diff --git a/erd.svg b/erd.svg new file mode 100644 index 0000000..309a8a3 --- /dev/null +++ b/erd.svg @@ -0,0 +1,198 @@ + + + + + + +XStake + +XStake domain model + + +m_ActiveStorage::Attachment + +ActiveStorage::Attachment + +blob_id +integer (8) ∗ FK +name +string ∗ +record_id +integer (8) ∗ FK +record_type +string ∗ + + + +m_ActiveStorage::Blob + +ActiveStorage::Blob + +byte_size +integer (8) ∗ +checksum +string ∗ +content_type +string +filename +string ∗ +key +string ∗ +metadata +text +service_name +string ∗ + + + +m_ActiveStorage::Blob->m_ActiveStorage::Attachment + + + + +m_ActiveStorage::Blob->m_ActiveStorage::Blob + + + + +m_ActiveStorage::VariantRecord + +ActiveStorage::VariantRecord + +blob_id +integer (8) ∗ FK +variation_digest +string ∗ + + + +m_ActiveStorage::Blob->m_ActiveStorage::VariantRecord + + + + + +m_ActiveStorage::VariantRecord->m_ActiveStorage::Attachment + + + + +m_AdminUser + +AdminUser + +email +string ∗ U +encrypted_password +string ∗ +remember_created_at +datetime +reset_password_sent_at +datetime +reset_password_token +string + + + +m_Balance + +Balance + +amount +decimal (20,10) ∗ +currency_id +integer (8) ∗ FK +user_id +integer (8) ∗ FK + + + +m_Currency + +Currency + +name +string ∗ + + + +m_Currency->m_Balance + + + + + +m_FiatBalance + +FiatBalance + +amount_cents +integer ∗ +amount_currency +string ∗ +user_id +integer (8) ∗ FK + + + +m_User + +User + +email +string ∗ U +encrypted_password +string ∗ +first_name +string ∗ +last_name +string ∗ +remember_created_at +datetime +reset_password_sent_at +datetime +reset_password_token +string + + + +m_User->m_Balance + + + + +m_User->m_FiatBalance + + + + +m_UserDocument + +UserDocument + +status +string ∗ +user_id +integer (8) ∗ FK + + + +m_User->m_UserDocument + + + + + +m_UserDocument->m_ActiveStorage::Attachment + + + + +m_UserDocument->m_ActiveStorage::Blob + + + + diff --git a/lib/tasks/auto_generate_diagram.rake b/lib/tasks/auto_generate_diagram.rake new file mode 100644 index 0000000..b7be980 --- /dev/null +++ b/lib/tasks/auto_generate_diagram.rake @@ -0,0 +1,7 @@ +# frozen_string_literal: true +# NOTE: only doing this in development as some production environments (Heroku) +# NOTE: are sensitive to local FS writes, and besides -- it's just not proper +# NOTE: to have a dev-mode tool do its thing in production. +if Rails.env.development? + RailsERD.load_tasks +end diff --git a/package.json b/package.json index 6a22fd4..11db0f0 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "autoprefixer": "^9", "babel-plugin-macros": "^3.1.0", "babel-plugin-relay": "^11.0.2", + "bignumber.js": "^9.0.1", "classnames": "^2.3.1", "postcss": "^7", "ramda": "^0.27.1", @@ -46,6 +47,7 @@ "eslint": "^7.32.0", "eslint-config-vtex": "^14.1.0", "eslint-config-vtex-react": "^8.1.0", + "eslint-plugin-relay": "^1.8.2", "graphql": "^15.5.1", "prettier": "^2.3.2", "relay-compiler": "^11.0.2", diff --git a/spec/factories/admin_users.rb b/spec/factories/admin_users.rb new file mode 100644 index 0000000..10f906b --- /dev/null +++ b/spec/factories/admin_users.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: admin_users +# +# id :bigint not null, primary key +# email :string default(""), not null +# encrypted_password :string default(""), not null +# remember_created_at :datetime +# reset_password_sent_at :datetime +# reset_password_token :string +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_admin_users_on_email (email) UNIQUE +# index_admin_users_on_reset_password_token (reset_password_token) UNIQUE +# +FactoryBot.define do + factory :admin_user do + sequence(:email) { |n| "admin-#{n}@example.com" } + password { "password" } + end +end diff --git a/spec/factories/balances.rb b/spec/factories/balances.rb new file mode 100644 index 0000000..1aa9df3 --- /dev/null +++ b/spec/factories/balances.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: balances +# +# id :bigint not null, primary key +# amount :decimal(20, 10) default(0.0), not null +# created_at :datetime not null +# updated_at :datetime not null +# currency_id :bigint not null +# user_id :bigint not null +# +# Indexes +# +# index_balances_on_currency_id (currency_id) +# index_balances_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (currency_id => currencies.id) +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :balance do + association :user + association :currency + amount { (rand * (10000 - 0) + 0) } + end +end diff --git a/spec/factories/currencies.rb b/spec/factories/currencies.rb new file mode 100644 index 0000000..e294e90 --- /dev/null +++ b/spec/factories/currencies.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: currencies +# +# id :bigint not null, primary key +# name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +FactoryBot.define do + factory :currency do + name { "CAKE" } + end +end diff --git a/spec/factories/fiat_balances.rb b/spec/factories/fiat_balances.rb new file mode 100644 index 0000000..37ac2a4 --- /dev/null +++ b/spec/factories/fiat_balances.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: fiat_balances +# +# id :bigint not null, primary key +# amount_cents :integer default(0), not null +# amount_currency :string default("BRL"), not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_fiat_balances_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :fiat_balance do + association :user + amount_currency { "BRL" } + amount_cents { Faker::Number.number(digits: 10) } + end +end diff --git a/spec/factories/user_documents.rb b/spec/factories/user_documents.rb new file mode 100644 index 0000000..a12861e --- /dev/null +++ b/spec/factories/user_documents.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: user_documents +# +# id :bigint not null, primary key +# status :string not null +# created_at :datetime not null +# updated_at :datetime not null +# user_id :bigint not null +# +# Indexes +# +# index_user_documents_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (user_id => users.id) +# +FactoryBot.define do + factory :user_document do + association :user + status { :pending_review } + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 0000000..fda8d14 --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: users +# +# id :bigint not null, primary key +# email :string default(""), not null +# encrypted_password :string default(""), not null +# first_name :string not null +# last_name :string not null +# remember_created_at :datetime +# reset_password_sent_at :datetime +# reset_password_token :string +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_users_on_email (email) UNIQUE +# index_users_on_reset_password_token (reset_password_token) UNIQUE +# +FactoryBot.define do + factory :user do + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + email { Faker::Internet.email } + password { "password" } + end +end diff --git a/spec/graphql/inputs/user_attributes_input_spec.rb b/spec/graphql/inputs/user_attributes_input_spec.rb deleted file mode 100644 index d3fe858..0000000 --- a/spec/graphql/inputs/user_attributes_input_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true -require "rails_helper" - -RSpec.describe(Inputs::UserAttributesInput) do - subject { described_class } - - describe "arguments" do - it { is_expected.to(accept_argument(:first_name).of_type("String!")) } - it { is_expected.to(accept_argument(:last_name).of_type("String!")) } - end -end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 8845843..ce70b21 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -31,6 +31,7 @@ RSpec.describe(User, type: :model) do describe "associations" do it { is_expected.to(have_many(:documents)) } - it { is_expected.to(have_many(:balances)) } + it { is_expected.to(have_one(:balance)) } + it { is_expected.to(have_one(:fiat_balance)) } end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 990e786..edf45e1 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -66,6 +66,9 @@ RSpec.configure do |config| config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") + + # Add FactoryBot + config.include(FactoryBot::Syntax::Methods) end Shoulda::Matchers.configure do |config| diff --git a/spec/views/home/index.html.erb_spec.rb b/spec/views/home/index.html.erb_spec.rb index 5399492..c26ae9b 100644 --- a/spec/views/home/index.html.erb_spec.rb +++ b/spec/views/home/index.html.erb_spec.rb @@ -2,5 +2,9 @@ require "rails_helper" RSpec.describe("home/index.html.erb", type: :view) do - pending "add some examples to (or delete) #{__FILE__}" + it "render div with id root" do + render + + expect(rendered).to(eq("")) + end end diff --git a/yarn.lock b/yarn.lock index 1c6891a..f412efe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2024,6 +2024,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bignumber.js@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -3558,6 +3563,13 @@ eslint-plugin-react@^7.20.6: resolve "^2.0.0-next.3" string.prototype.matchall "^4.0.5" +eslint-plugin-relay@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.8.2.tgz#925f59231e39dfc076b3cbb39ef793c13381579e" + integrity sha512-bqIfXJnPMd6iHPitONSi8JqxrWQWaX4Rqk1shusKDlUu5vswUgoqOEGgqE8nDu6SmejBUZMz0vY+ROvq5wqOsw== + dependencies: + graphql "^14.0.0 || ^15.0.0" + eslint-plugin-vtex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-vtex/-/eslint-plugin-vtex-2.1.0.tgz#cb328b5d6f4bba400cf57d5dca679985ac768e2a" @@ -4251,7 +4263,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== -graphql@^15.5.1: +"graphql@^14.0.0 || ^15.0.0", graphql@^15.5.1: version "15.5.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad" integrity sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw==