focus_nfe 1.0.0
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.
- checksums.yaml +7 -0
- data/.git-hooks/pre_push/steep.rb +18 -0
- data/.git-hooks/pre_push/yard_doc.rb +18 -0
- data/.gitattributes +1 -0
- data/.overcommit.yml +69 -0
- data/.rspec +3 -0
- data/.yardopts +11 -0
- data/CHANGELOG.md +77 -0
- data/CLAUDE.md +118 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +348 -0
- data/Rakefile +105 -0
- data/data/schemas/schema_cte.json +2793 -0
- data/data/schemas/schema_cte_os.json +1335 -0
- data/data/schemas/schema_cte_os_transporte_rodoviario.json +109 -0
- data/data/schemas/schema_cte_transporte_aereo.json +115 -0
- data/data/schemas/schema_cte_transporte_aquaviario.json +174 -0
- data/data/schemas/schema_cte_transporte_dutoviario.json +65 -0
- data/data/schemas/schema_cte_transporte_ferroviario.json +144 -0
- data/data/schemas/schema_cte_transporte_multimodal.json +45 -0
- data/data/schemas/schema_cte_transporte_rodoviario.json +78 -0
- data/data/schemas/schema_dce.json +549 -0
- data/data/schemas/schema_mdfe.json +1102 -0
- data/data/schemas/schema_mdfe_transporte_aereo.json +44 -0
- data/data/schemas/schema_mdfe_transporte_aquaviario.json +209 -0
- data/data/schemas/schema_mdfe_transporte_ferroviario.json +99 -0
- data/data/schemas/schema_mdfe_transporte_rodoviario.json +628 -0
- data/data/schemas/schema_nfcom.json +1859 -0
- data/data/schemas/schema_nfe.json +4750 -0
- data/data/schemas/schema_nfe_forma_pagamento.json +97 -0
- data/data/schemas/schema_nfe_item.json +2574 -0
- data/data/schemas/schema_nfgas.json +2316 -0
- data/data/schemas/schema_nfse_nacional.json +1847 -0
- data/data/schemas/schema_nfse_recebida.json +548 -0
- data/lib/focus_nfe/client.rb +162 -0
- data/lib/focus_nfe/configuration.rb +104 -0
- data/lib/focus_nfe/errors.rb +123 -0
- data/lib/focus_nfe/esquemas/campo.rb +171 -0
- data/lib/focus_nfe/esquemas/catalogo.rb +34 -0
- data/lib/focus_nfe/esquemas/decimal.rb +66 -0
- data/lib/focus_nfe/esquemas/esquema.rb +72 -0
- data/lib/focus_nfe/esquemas/validador.rb +87 -0
- data/lib/focus_nfe/http/adapter.rb +25 -0
- data/lib/focus_nfe/http/adapters/net_http.rb +99 -0
- data/lib/focus_nfe/http/authentication.rb +23 -0
- data/lib/focus_nfe/http/connection.rb +118 -0
- data/lib/focus_nfe/http/logging.rb +100 -0
- data/lib/focus_nfe/http/response.rb +75 -0
- data/lib/focus_nfe/modelos/documento.rb +113 -0
- data/lib/focus_nfe/modelos/inutilizacao.rb +75 -0
- data/lib/focus_nfe/modelos/pagina.rb +54 -0
- data/lib/focus_nfe/recursos/backups.rb +17 -0
- data/lib/focus_nfe/recursos/base.rb +91 -0
- data/lib/focus_nfe/recursos/ceps.rb +16 -0
- data/lib/focus_nfe/recursos/cfops.rb +16 -0
- data/lib/focus_nfe/recursos/cnaes.rb +16 -0
- data/lib/focus_nfe/recursos/cnpjs.rb +13 -0
- data/lib/focus_nfe/recursos/concerns/baixavel.rb +41 -0
- data/lib/focus_nfe/recursos/concerns/baixavel_eventos.rb +34 -0
- data/lib/focus_nfe/recursos/concerns/cancelavel.rb +25 -0
- data/lib/focus_nfe/recursos/concerns/conciliavel.rb +66 -0
- data/lib/focus_nfe/recursos/concerns/consultavel.rb +26 -0
- data/lib/focus_nfe/recursos/concerns/corrigivel.rb +45 -0
- data/lib/focus_nfe/recursos/concerns/corrigivel_cte.rb +60 -0
- data/lib/focus_nfe/recursos/concerns/emitivel.rb +51 -0
- data/lib/focus_nfe/recursos/concerns/enviavel.rb +40 -0
- data/lib/focus_nfe/recursos/concerns/eventavel.rb +46 -0
- data/lib/focus_nfe/recursos/concerns/inutilizavel.rb +96 -0
- data/lib/focus_nfe/recursos/concerns/listavel.rb +22 -0
- data/lib/focus_nfe/recursos/concerns/localizavel.rb +22 -0
- data/lib/focus_nfe/recursos/concerns/notificavel.rb +23 -0
- data/lib/focus_nfe/recursos/concerns/removivel.rb +20 -0
- data/lib/focus_nfe/recursos/concerns/visualizavel.rb +28 -0
- data/lib/focus_nfe/recursos/cte.rb +35 -0
- data/lib/focus_nfe/recursos/cte_os.rb +29 -0
- data/lib/focus_nfe/recursos/ctes_recebidas.rb +38 -0
- data/lib/focus_nfe/recursos/dce.rb +16 -0
- data/lib/focus_nfe/recursos/emails_bloqueados.rb +31 -0
- data/lib/focus_nfe/recursos/empresas.rb +35 -0
- data/lib/focus_nfe/recursos/mdfe.rb +78 -0
- data/lib/focus_nfe/recursos/municipios.rb +60 -0
- data/lib/focus_nfe/recursos/ncms.rb +16 -0
- data/lib/focus_nfe/recursos/nfce.rb +19 -0
- data/lib/focus_nfe/recursos/nfcom.rb +16 -0
- data/lib/focus_nfe/recursos/nfe.rb +106 -0
- data/lib/focus_nfe/recursos/nfes_recebidas.rb +56 -0
- data/lib/focus_nfe/recursos/nfgas.rb +16 -0
- data/lib/focus_nfe/recursos/nfse.rb +18 -0
- data/lib/focus_nfe/recursos/nfse_nacional.rb +16 -0
- data/lib/focus_nfe/recursos/nfses_nacionais_recebidas.rb +21 -0
- data/lib/focus_nfe/recursos/webhooks.rb +22 -0
- data/lib/focus_nfe/version.rb +6 -0
- data/lib/focus_nfe/webhook.rb +68 -0
- data/lib/focus_nfe.rb +124 -0
- data/sig/focus_nfe/client.rbs +38 -0
- data/sig/focus_nfe/configuration.rbs +29 -0
- data/sig/focus_nfe/errors.rbs +59 -0
- data/sig/focus_nfe/esquemas/campo.rbs +47 -0
- data/sig/focus_nfe/esquemas/catalogo.rbs +8 -0
- data/sig/focus_nfe/esquemas/decimal.rbs +25 -0
- data/sig/focus_nfe/esquemas/esquema.rbs +30 -0
- data/sig/focus_nfe/esquemas/validador.rbs +20 -0
- data/sig/focus_nfe/http/adapter.rbs +7 -0
- data/sig/focus_nfe/http/adapters/net_http.rbs +25 -0
- data/sig/focus_nfe/http/authentication.rbs +9 -0
- data/sig/focus_nfe/http/connection.rbs +32 -0
- data/sig/focus_nfe/http/logging.rbs +30 -0
- data/sig/focus_nfe/http/response.rbs +28 -0
- data/sig/focus_nfe/modelos/documento.rbs +34 -0
- data/sig/focus_nfe/modelos/inutilizacao.rbs +24 -0
- data/sig/focus_nfe/modelos/pagina.rbs +21 -0
- data/sig/focus_nfe/recursos/backups.rbs +7 -0
- data/sig/focus_nfe/recursos/base.rbs +25 -0
- data/sig/focus_nfe/recursos/ceps.rbs +10 -0
- data/sig/focus_nfe/recursos/cfops.rbs +10 -0
- data/sig/focus_nfe/recursos/cnaes.rbs +10 -0
- data/sig/focus_nfe/recursos/cnpjs.rbs +7 -0
- data/sig/focus_nfe/recursos/concerns/baixavel.rbs +12 -0
- data/sig/focus_nfe/recursos/concerns/baixavel_eventos.rbs +14 -0
- data/sig/focus_nfe/recursos/concerns/cancelavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/conciliavel.rbs +15 -0
- data/sig/focus_nfe/recursos/concerns/consultavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/corrigivel.rbs +15 -0
- data/sig/focus_nfe/recursos/concerns/corrigivel_cte.rbs +17 -0
- data/sig/focus_nfe/recursos/concerns/emitivel.rbs +14 -0
- data/sig/focus_nfe/recursos/concerns/enviavel.rbs +15 -0
- data/sig/focus_nfe/recursos/concerns/eventavel.rbs +12 -0
- data/sig/focus_nfe/recursos/concerns/inutilizavel.rbs +20 -0
- data/sig/focus_nfe/recursos/concerns/listavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/localizavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/notificavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/removivel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/visualizavel.rbs +9 -0
- data/sig/focus_nfe/recursos/cte.rbs +17 -0
- data/sig/focus_nfe/recursos/cte_os.rbs +17 -0
- data/sig/focus_nfe/recursos/ctes_recebidas.rbs +14 -0
- data/sig/focus_nfe/recursos/dce.rbs +10 -0
- data/sig/focus_nfe/recursos/emails_bloqueados.rbs +12 -0
- data/sig/focus_nfe/recursos/empresas.rbs +12 -0
- data/sig/focus_nfe/recursos/mdfe.rbs +21 -0
- data/sig/focus_nfe/recursos/municipios.rbs +19 -0
- data/sig/focus_nfe/recursos/ncms.rbs +10 -0
- data/sig/focus_nfe/recursos/nfce.rbs +12 -0
- data/sig/focus_nfe/recursos/nfcom.rbs +10 -0
- data/sig/focus_nfe/recursos/nfe.rbs +23 -0
- data/sig/focus_nfe/recursos/nfes_recebidas.rbs +16 -0
- data/sig/focus_nfe/recursos/nfgas.rbs +10 -0
- data/sig/focus_nfe/recursos/nfse.rbs +11 -0
- data/sig/focus_nfe/recursos/nfse_nacional.rbs +10 -0
- data/sig/focus_nfe/recursos/nfses_nacionais_recebidas.rbs +11 -0
- data/sig/focus_nfe/recursos/webhooks.rbs +11 -0
- data/sig/focus_nfe/webhook.rbs +11 -0
- data/sig/focus_nfe.rbs +10 -0
- data/spec/focus_nfe/client_spec.rb +208 -0
- data/spec/focus_nfe/configuration_spec.rb +121 -0
- data/spec/focus_nfe/errors_mapping_spec.rb +68 -0
- data/spec/focus_nfe/errors_spec.rb +107 -0
- data/spec/focus_nfe/esquemas/campo_spec.rb +291 -0
- data/spec/focus_nfe/esquemas/decimal_spec.rb +54 -0
- data/spec/focus_nfe/esquemas/esquema_spec.rb +73 -0
- data/spec/focus_nfe/esquemas/validador_spec.rb +167 -0
- data/spec/focus_nfe/esquemas_spec.rb +42 -0
- data/spec/focus_nfe/http/adapter_spec.rb +8 -0
- data/spec/focus_nfe/http/adapters/net_http_spec.rb +181 -0
- data/spec/focus_nfe/http/authentication_spec.rb +24 -0
- data/spec/focus_nfe/http/connection_spec.rb +255 -0
- data/spec/focus_nfe/http/logging_spec.rb +83 -0
- data/spec/focus_nfe/http/response_spec.rb +161 -0
- data/spec/focus_nfe/modelos/documento_spec.rb +150 -0
- data/spec/focus_nfe/modelos/inutilizacao_spec.rb +91 -0
- data/spec/focus_nfe/modelos/pagina_spec.rb +77 -0
- data/spec/focus_nfe/recursos/backups_spec.rb +29 -0
- data/spec/focus_nfe/recursos/base_spec.rb +56 -0
- data/spec/focus_nfe/recursos/ceps_spec.rb +16 -0
- data/spec/focus_nfe/recursos/cfops_spec.rb +16 -0
- data/spec/focus_nfe/recursos/cnaes_spec.rb +20 -0
- data/spec/focus_nfe/recursos/cnpjs_spec.rb +11 -0
- data/spec/focus_nfe/recursos/concerns/emitivel_validacao_spec.rb +158 -0
- data/spec/focus_nfe/recursos/cte_os_spec.rb +9 -0
- data/spec/focus_nfe/recursos/cte_spec.rb +9 -0
- data/spec/focus_nfe/recursos/ctes_recebidas_spec.rb +56 -0
- data/spec/focus_nfe/recursos/dce_spec.rb +8 -0
- data/spec/focus_nfe/recursos/emails_bloqueados_spec.rb +29 -0
- data/spec/focus_nfe/recursos/empresas_spec.rb +45 -0
- data/spec/focus_nfe/recursos/mdfe_spec.rb +100 -0
- data/spec/focus_nfe/recursos/municipios_spec.rb +58 -0
- data/spec/focus_nfe/recursos/ncms_spec.rb +16 -0
- data/spec/focus_nfe/recursos/nfce_spec.rb +10 -0
- data/spec/focus_nfe/recursos/nfcom_spec.rb +8 -0
- data/spec/focus_nfe/recursos/nfe_spec.rb +262 -0
- data/spec/focus_nfe/recursos/nfes_recebidas_spec.rb +87 -0
- data/spec/focus_nfe/recursos/nfgas_spec.rb +8 -0
- data/spec/focus_nfe/recursos/nfse_nacional_spec.rb +8 -0
- data/spec/focus_nfe/recursos/nfse_spec.rb +9 -0
- data/spec/focus_nfe/recursos/nfses_nacionais_recebidas_spec.rb +17 -0
- data/spec/focus_nfe/recursos/webhooks_spec.rb +22 -0
- data/spec/focus_nfe/webhook_spec.rb +66 -0
- data/spec/focus_nfe_global_configuration_spec.rb +70 -0
- data/spec/focus_nfe_require_spec.rb +87 -0
- data/spec/focus_nfe_spec.rb +11 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/support/shared_examples/recurso_fiscal.rb +445 -0
- data/spec/support/shared_examples/recurso_leitura.rb +217 -0
- data/tools/pull_fields.rb +62 -0
- metadata +420 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Modelos::Inutilizacao do
|
|
4
|
+
def response(body:, status: 200)
|
|
5
|
+
FocusNfe::HTTP::Response.new(
|
|
6
|
+
status: status,
|
|
7
|
+
headers: { "Content-Type" => "application/json" },
|
|
8
|
+
body: JSON.generate(body)
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe ".from_response" do
|
|
13
|
+
it "mapeia status, status_sefaz e mensagem_sefaz", :aggregate_failures do
|
|
14
|
+
corpo = { "status" => "autorizado", "status_sefaz" => "102", "mensagem_sefaz" => "ok" }
|
|
15
|
+
inut = described_class.from_response(response(body: corpo))
|
|
16
|
+
|
|
17
|
+
expect(inut).to have_attributes(status: "autorizado", status_sefaz: "102", mensagem_sefaz: "ok")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "mapeia serie, numero_inicial e numero_final", :aggregate_failures do
|
|
21
|
+
corpo = { "serie" => "1", "numero_inicial" => "10", "numero_final" => "20" }
|
|
22
|
+
inut = described_class.from_response(response(body: corpo))
|
|
23
|
+
|
|
24
|
+
expect(inut).to have_attributes(serie: "1", numero_inicial: "10", numero_final: "20")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "expõe protocolo a partir de protocolo_sefaz" do
|
|
28
|
+
inut = described_class.from_response(response(body: { "protocolo_sefaz" => "135200" }))
|
|
29
|
+
|
|
30
|
+
expect(inut.protocolo).to eq("135200")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "guarda a resposta original para inspeção" do
|
|
34
|
+
resp = response(body: { "status" => "autorizado" })
|
|
35
|
+
|
|
36
|
+
expect(described_class.from_response(resp).response).to be(resp)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "usa dados vazios quando o corpo não é um Hash", :aggregate_failures do
|
|
40
|
+
inut = described_class.from_response(response(body: ["x"]))
|
|
41
|
+
|
|
42
|
+
expect(inut.dados).to eq({})
|
|
43
|
+
expect(inut.status).to be_nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe ".from_item" do
|
|
48
|
+
it "constrói a partir de um Hash cru, sem resposta", :aggregate_failures do
|
|
49
|
+
inut = described_class.from_item("status" => "autorizado", "protocolo_sefaz" => "1")
|
|
50
|
+
|
|
51
|
+
expect(inut.response).to be_nil
|
|
52
|
+
expect(inut).to have_attributes(status: "autorizado", protocolo: "1")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "usa dados vazios quando o item não é um Hash" do
|
|
56
|
+
expect(described_class.from_item(nil).dados).to eq({})
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#autorizado?" do
|
|
61
|
+
def inut(status)
|
|
62
|
+
described_class.from_item("status" => status)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "é verdadeiro só para 'autorizado'", :aggregate_failures do
|
|
66
|
+
expect(inut("autorizado")).to be_autorizado
|
|
67
|
+
expect(inut("erro_autorizacao")).not_to be_autorizado
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "acesso bruto" do
|
|
72
|
+
subject(:inut) do
|
|
73
|
+
described_class.from_item("status" => "autorizado", "cnpj" => "123", "modelo" => "55", "caminho_xml" => "/x.xml")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "expõe o Hash cru via #dados" do
|
|
77
|
+
expect(inut.dados).to include("cnpj" => "123", "modelo" => "55", "caminho_xml" => "/x.xml")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "delega #[] ao Hash para campos não mapeados", :aggregate_failures do
|
|
81
|
+
expect(inut["cnpj"]).to eq("123")
|
|
82
|
+
expect(inut["caminho_xml"]).to eq("/x.xml")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe "imutabilidade" do
|
|
87
|
+
it "congela a instância" do
|
|
88
|
+
expect(described_class.from_item("status" => "autorizado")).to be_frozen
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Modelos::Pagina do
|
|
4
|
+
def response(body:, headers: {})
|
|
5
|
+
FocusNfe::HTTP::Response.new(
|
|
6
|
+
status: 200,
|
|
7
|
+
headers: { "Content-Type" => "application/json" }.merge(headers),
|
|
8
|
+
body: JSON.generate(body)
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe ".from_response" do
|
|
13
|
+
it "expõe os itens do corpo (Array)" do
|
|
14
|
+
pagina = described_class.from_response(response(body: [{ "a" => 1 }, { "a" => 2 }]))
|
|
15
|
+
|
|
16
|
+
expect(pagina.itens).to eq([{ "a" => 1 }, { "a" => 2 }])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "usa lista vazia quando o corpo não é um Array" do
|
|
20
|
+
pagina = described_class.from_response(response(body: { "erro" => "x" }))
|
|
21
|
+
|
|
22
|
+
expect(pagina.itens).to eq([])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "lê total e versao_maxima dos headers de paginação", :aggregate_failures do
|
|
26
|
+
pagina = described_class.from_response(
|
|
27
|
+
response(body: [], headers: { "X-Total-Count" => "42", "X-Max-Version" => "7" })
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
expect(pagina.total).to eq(42)
|
|
31
|
+
expect(pagina.versao_maxima).to eq(7)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "deixa total e versao_maxima nil quando os headers estão ausentes", :aggregate_failures do
|
|
35
|
+
pagina = described_class.from_response(response(body: []))
|
|
36
|
+
|
|
37
|
+
expect(pagina.total).to be_nil
|
|
38
|
+
expect(pagina.versao_maxima).to be_nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "guarda a resposta original" do
|
|
42
|
+
resp = response(body: [])
|
|
43
|
+
|
|
44
|
+
expect(described_class.from_response(resp).response).to be(resp)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "enumerável" do
|
|
49
|
+
subject(:pagina) { described_class.from_response(response(body: [1, 2, 3])) }
|
|
50
|
+
|
|
51
|
+
it "itera com cada", :aggregate_failures do
|
|
52
|
+
coletados = []
|
|
53
|
+
retorno = pagina.cada { |item| coletados << item }
|
|
54
|
+
|
|
55
|
+
expect(coletados).to eq([1, 2, 3])
|
|
56
|
+
expect(retorno).to be(pagina)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "compõe os helpers de Enumerable (map/select)", :aggregate_failures do
|
|
60
|
+
expect(pagina.map { |i| i * 2 }).to eq([2, 4, 6])
|
|
61
|
+
expect(pagina.select(&:even?)).to eq([2])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "devolve um Enumerator quando chamado sem bloco", :aggregate_failures do
|
|
65
|
+
enum = pagina.cada
|
|
66
|
+
|
|
67
|
+
expect(enum).to be_a(Enumerator)
|
|
68
|
+
expect(enum.to_a).to eq([1, 2, 3])
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe "imutabilidade" do
|
|
73
|
+
it "congela a instância" do
|
|
74
|
+
expect(described_class.from_response(response(body: []))).to be_frozen
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Backups do
|
|
4
|
+
include_context "com recurso conectado"
|
|
5
|
+
|
|
6
|
+
let(:cnpj) { "12345678000123" }
|
|
7
|
+
|
|
8
|
+
it "usa o caminho_base 'backups'" do
|
|
9
|
+
expect(recurso.caminho_base).to eq("backups")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#consultar" do
|
|
13
|
+
it "faz GET em /v2/backups/{cnpj}.json e devolve o corpo cru" do
|
|
14
|
+
stub_get("backups/#{cnpj}.json", body: '[{"mes":"202605"}]')
|
|
15
|
+
|
|
16
|
+
expect(recurso.consultar(cnpj)).to eq([{ "mes" => "202605" }])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "escapa o cnpj, sem injetar query nem traversal no path" do
|
|
20
|
+
stub_request(:get, /focusnfe/).to_return(status: 200, body: "[]", headers: json)
|
|
21
|
+
|
|
22
|
+
recurso.consultar("../empresas/1?x=y")
|
|
23
|
+
|
|
24
|
+
enviado = a_request(:get, /focusnfe/)
|
|
25
|
+
.with { |req| req.uri.query.nil? && req.uri.path.include?("..%2Fempresas%2F1%3Fx") }
|
|
26
|
+
expect(enviado).to have_been_made
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Base do
|
|
4
|
+
let(:connection) { instance_double(FocusNfe::HTTP::Connection) }
|
|
5
|
+
|
|
6
|
+
describe "DSL caminho_base" do
|
|
7
|
+
it "expõe o caminho declarado na classe via método de instância" do
|
|
8
|
+
classe = Class.new(described_class) { caminho_base "nfe" }
|
|
9
|
+
|
|
10
|
+
expect(classe.new(connection).caminho_base).to eq("nfe")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "é por classe — subclasses não vazam entre si", :aggregate_failures do
|
|
14
|
+
uma = Class.new(described_class) { caminho_base "nfe" }
|
|
15
|
+
outra = Class.new(described_class) { caminho_base "nfce" }
|
|
16
|
+
|
|
17
|
+
expect(uma.new(connection).caminho_base).to eq("nfe")
|
|
18
|
+
expect(outra.new(connection).caminho_base).to eq("nfce")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#validar_referencia!" do
|
|
23
|
+
subject(:recurso) { Class.new(described_class) { caminho_base "nfe" }.new(connection) }
|
|
24
|
+
|
|
25
|
+
it "aceita refs alfanuméricas com hífen/underscore", :aggregate_failures do
|
|
26
|
+
expect { recurso.send(:validar_referencia!, "pedido-42") }.not_to raise_error
|
|
27
|
+
expect { recurso.send(:validar_referencia!, "venda_1001") }.not_to raise_error
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "rejeita refs com espaço ou vazias", :aggregate_failures do
|
|
31
|
+
expect { recurso.send(:validar_referencia!, "a b") }.to raise_error(ArgumentError)
|
|
32
|
+
expect { recurso.send(:validar_referencia!, "") }.to raise_error(ArgumentError)
|
|
33
|
+
expect { recurso.send(:validar_referencia!, nil) }.to raise_error(ArgumentError)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "#caminho_referencia" do
|
|
38
|
+
subject(:recurso) { Class.new(described_class) { caminho_base "nfe" }.new(connection) }
|
|
39
|
+
|
|
40
|
+
it "combina o caminho base com a ref" do
|
|
41
|
+
expect(recurso.send(:caminho_referencia, "pedido-42")).to eq("nfe/pedido-42")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "preserva identificadores comuns (dígitos, hífen, underscore, ponto)", :aggregate_failures do
|
|
45
|
+
expect(recurso.send(:caminho_referencia, "12345678000190")).to eq("nfe/12345678000190")
|
|
46
|
+
expect(recurso.send(:caminho_referencia, "venda_1001")).to eq("nfe/venda_1001")
|
|
47
|
+
expect(recurso.send(:caminho_referencia, "35200114200166000187.55")).to eq("nfe/35200114200166000187.55")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "escapa caracteres que sequestrariam o path ou injetariam query", :aggregate_failures do
|
|
51
|
+
expect(recurso.send(:caminho_referencia, "a/b")).to eq("nfe/a%2Fb")
|
|
52
|
+
expect(recurso.send(:caminho_referencia, "x?y")).to eq("nfe/x%3Fy")
|
|
53
|
+
expect(recurso.send(:caminho_referencia, "../../empresas")).to eq("nfe/..%2F..%2Fempresas")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Ceps do
|
|
4
|
+
it_behaves_like "um recurso listável", "ceps"
|
|
5
|
+
it_behaves_like "um recurso localizável", "ceps"
|
|
6
|
+
|
|
7
|
+
include_context "com recurso conectado"
|
|
8
|
+
|
|
9
|
+
describe "#buscar" do
|
|
10
|
+
it "é um apelido de #listar e devolve uma Pagina" do
|
|
11
|
+
stub_get("ceps", query: { uf: "AM", logradouro: "Eduardo" }, body: "[]")
|
|
12
|
+
|
|
13
|
+
expect(recurso.buscar(uf: "AM", logradouro: "Eduardo")).to be_a(FocusNfe::Modelos::Pagina)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Cfops do
|
|
4
|
+
it_behaves_like "um recurso listável", "cfops"
|
|
5
|
+
it_behaves_like "um recurso localizável", "cfops"
|
|
6
|
+
|
|
7
|
+
include_context "com recurso conectado"
|
|
8
|
+
|
|
9
|
+
describe "#buscar" do
|
|
10
|
+
it "é um apelido de #listar" do
|
|
11
|
+
stub_get("cfops", query: { descricao: "venda" }, body: "[]")
|
|
12
|
+
|
|
13
|
+
expect(recurso.buscar(descricao: "venda")).to be_a(FocusNfe::Modelos::Pagina)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Cnaes do
|
|
4
|
+
it_behaves_like "um recurso listável", "codigos_cnae"
|
|
5
|
+
it_behaves_like "um recurso localizável", "codigos_cnae"
|
|
6
|
+
|
|
7
|
+
include_context "com recurso conectado"
|
|
8
|
+
|
|
9
|
+
it "usa o caminho_base 'codigos_cnae'" do
|
|
10
|
+
expect(recurso.caminho_base).to eq("codigos_cnae")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#buscar" do
|
|
14
|
+
it "é um apelido de #listar" do
|
|
15
|
+
stub_get("codigos_cnae", query: { descricao: "software" }, body: "[]")
|
|
16
|
+
|
|
17
|
+
expect(recurso.buscar(descricao: "software")).to be_a(FocusNfe::Modelos::Pagina)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Cnpjs do
|
|
4
|
+
it_behaves_like "um recurso localizável", "cnpjs"
|
|
5
|
+
|
|
6
|
+
include_context "com recurso conectado"
|
|
7
|
+
|
|
8
|
+
it "não expõe listagem" do
|
|
9
|
+
expect(recurso).not_to respond_to(:listar)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Concerns::Emitivel do
|
|
4
|
+
let(:client) { FocusNfe::Client.new(token_empresa: "tok", environment: :homologacao) }
|
|
5
|
+
let(:nfe) { FocusNfe::Recursos::Nfe.new(client.connection) }
|
|
6
|
+
let(:nfce) { FocusNfe::Recursos::Nfce.new(client.connection) }
|
|
7
|
+
let(:cte) { FocusNfe::Recursos::Cte.new(client.connection) }
|
|
8
|
+
let(:cte_os) { FocusNfe::Recursos::CteOs.new(client.connection) }
|
|
9
|
+
let(:mdfe) { FocusNfe::Recursos::Mdfe.new(client.connection) }
|
|
10
|
+
|
|
11
|
+
def json = { "Content-Type" => "application/json" }
|
|
12
|
+
def processando = '{"status":"processando_autorizacao"}'
|
|
13
|
+
def homologacao = "https://homologacao.focusnfe.com.br"
|
|
14
|
+
|
|
15
|
+
def stub_emissao(path, status: 202)
|
|
16
|
+
stub_request(:post, "#{homologacao}/v2/#{path}").to_return(status: status, body: processando, headers: json)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#emitir com validar: true" do
|
|
20
|
+
context "quando o documento tem schema empacotado" do
|
|
21
|
+
it "levanta ErroDeValidacao sem fazer requisição quando faltam obrigatórios", :aggregate_failures do
|
|
22
|
+
stub = stub_emissao("nfe?ref=pedido-1")
|
|
23
|
+
|
|
24
|
+
expect { nfe.emitir(ref: "pedido-1", dados: {}, validar: true) }
|
|
25
|
+
.to raise_error(FocusNfe::Esquemas::ErroDeValidacao)
|
|
26
|
+
expect(stub).not_to have_been_requested
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "emite normalmente quando os dados são válidos" do
|
|
30
|
+
esquema = FocusNfe::Esquemas::Esquema.new([{ "name" => "natureza_operacao", "type" => "String[1-60]" }])
|
|
31
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).with("nfe").and_return(esquema)
|
|
32
|
+
stub_emissao("nfe?ref=pedido-1")
|
|
33
|
+
|
|
34
|
+
nfe.emitir(ref: "pedido-1", dados: { "natureza_operacao" => "Venda" }, validar: true)
|
|
35
|
+
|
|
36
|
+
expect(a_request(:post, "#{homologacao}/v2/nfe?ref=pedido-1")).to have_been_made
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "não vaza o parâmetro validar para a query string" do
|
|
40
|
+
esquema = FocusNfe::Esquemas::Esquema.new([])
|
|
41
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).with("nfe").and_return(esquema)
|
|
42
|
+
stub_emissao("nfe?ref=pedido-1")
|
|
43
|
+
|
|
44
|
+
nfe.emitir(ref: "pedido-1", dados: {}, validar: true)
|
|
45
|
+
|
|
46
|
+
expect(a_request(:post, "#{homologacao}/v2/nfe").with(query: { "ref" => "pedido-1" })).to have_been_made
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "quando o documento tem modal condicional (CTe)" do
|
|
51
|
+
def stub_esquema_base_vazio
|
|
52
|
+
vazio = FocusNfe::Esquemas::Esquema.new([])
|
|
53
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).and_call_original
|
|
54
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).with("cte").and_return(vazio)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "valida o sub-esquema do modal e bloqueia a emissão" do
|
|
58
|
+
stub_esquema_base_vazio
|
|
59
|
+
|
|
60
|
+
expect do
|
|
61
|
+
cte.emitir(ref: "cte-1", dados: { "modal" => "01", "modal_rodoviario" => { "rntrc" => "1" } }, validar: true)
|
|
62
|
+
end.to raise_error(FocusNfe::Esquemas::ErroDeValidacao, /modal_rodoviario/)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "emite quando base e modal são válidos" do
|
|
66
|
+
stub_esquema_base_vazio
|
|
67
|
+
stub_emissao("cte?ref=cte-1")
|
|
68
|
+
|
|
69
|
+
cte.emitir(ref: "cte-1", dados: { "modal" => "01", "modal_rodoviario" => { "rntrc" => "12345678" } },
|
|
70
|
+
validar: true)
|
|
71
|
+
|
|
72
|
+
expect(a_request(:post, "#{homologacao}/v2/cte?ref=cte-1")).to have_been_made
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "quando o CTe OS tem modal condicional" do
|
|
77
|
+
def stub_cte_os_base_vazio
|
|
78
|
+
vazio = FocusNfe::Esquemas::Esquema.new([])
|
|
79
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).and_call_original
|
|
80
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).with("cte_os").and_return(vazio)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "valida o sub-esquema do modal e bloqueia a emissão" do
|
|
84
|
+
stub_cte_os_base_vazio
|
|
85
|
+
|
|
86
|
+
expect do
|
|
87
|
+
cte_os.emitir(ref: "cte-os-1", dados: { "modal" => "01", "modal_rodoviario" => { "placa" => "ABC1234" } },
|
|
88
|
+
validar: true)
|
|
89
|
+
end.to raise_error(FocusNfe::Esquemas::ErroDeValidacao, /modal_rodoviario\.placa/)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "emite quando base e modal são válidos" do
|
|
93
|
+
stub_cte_os_base_vazio
|
|
94
|
+
stub_emissao("cte_os?ref=cte-os-1")
|
|
95
|
+
|
|
96
|
+
cte_os.emitir(ref: "cte-os-1", dados: { "modal" => "01", "modal_rodoviario" => { "placa" => "AB12" } },
|
|
97
|
+
validar: true)
|
|
98
|
+
|
|
99
|
+
expect(a_request(:post, "#{homologacao}/v2/cte_os?ref=cte-os-1")).to have_been_made
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "não valida modal quando o campo modal não é 01" do
|
|
103
|
+
stub_cte_os_base_vazio
|
|
104
|
+
stub_emissao("cte_os?ref=cte-os-1")
|
|
105
|
+
|
|
106
|
+
cte_os.emitir(ref: "cte-os-1", dados: { "modal" => "02", "modal_rodoviario" => { "placa" => "ABC1234" } },
|
|
107
|
+
validar: true)
|
|
108
|
+
|
|
109
|
+
expect(a_request(:post, "#{homologacao}/v2/cte_os?ref=cte-os-1")).to have_been_made
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "quando a MDFe deduz o modal pela chave presente" do
|
|
114
|
+
def stub_mdfe_base_vazia
|
|
115
|
+
vazio = FocusNfe::Esquemas::Esquema.new([])
|
|
116
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).and_call_original
|
|
117
|
+
allow(FocusNfe::Esquemas::Esquema).to receive(:carregar).with("mdfe").and_return(vazio)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "valida o sub-esquema do modal presente e bloqueia a emissão" do
|
|
121
|
+
stub_mdfe_base_vazia
|
|
122
|
+
|
|
123
|
+
expect do
|
|
124
|
+
mdfe.emitir(ref: "mdfe-1", dados: { "modal_rodoviario" => {} }, validar: true)
|
|
125
|
+
end.to raise_error(FocusNfe::Esquemas::ErroDeValidacao, /modal_rodoviario/)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "emite quando nenhuma chave de modal está presente" do
|
|
129
|
+
stub_mdfe_base_vazia
|
|
130
|
+
stub_emissao("mdfe?ref=mdfe-1")
|
|
131
|
+
|
|
132
|
+
mdfe.emitir(ref: "mdfe-1", dados: { "cnpj_emitente" => "12345678000123" }, validar: true)
|
|
133
|
+
|
|
134
|
+
expect(a_request(:post, "#{homologacao}/v2/mdfe?ref=mdfe-1")).to have_been_made
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context "quando o documento não tem schema (pula silenciosamente)" do
|
|
139
|
+
it "emite sem validar" do
|
|
140
|
+
stub_emissao("nfce?ref=venda-1")
|
|
141
|
+
|
|
142
|
+
nfce.emitir(ref: "venda-1", dados: {}, validar: true)
|
|
143
|
+
|
|
144
|
+
expect(a_request(:post, "#{homologacao}/v2/nfce?ref=venda-1")).to have_been_made
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe "#emitir sem validar (padrão)" do
|
|
150
|
+
it "não valida mesmo com dados vazios" do
|
|
151
|
+
stub_emissao("nfe?ref=pedido-1")
|
|
152
|
+
|
|
153
|
+
nfe.emitir(ref: "pedido-1", dados: {})
|
|
154
|
+
|
|
155
|
+
expect(a_request(:post, "#{homologacao}/v2/nfe?ref=pedido-1")).to have_been_made
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::CteOs do
|
|
4
|
+
it_behaves_like "um recurso emitível", "cte_os"
|
|
5
|
+
it_behaves_like "um recurso consultável", "cte_os"
|
|
6
|
+
it_behaves_like "um recurso cancelável", "cte_os"
|
|
7
|
+
it_behaves_like "um recurso corrigível por campo", "cte_os"
|
|
8
|
+
it_behaves_like "um recurso notificável", "cte_os"
|
|
9
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Cte do
|
|
4
|
+
it_behaves_like "um recurso emitível", "cte"
|
|
5
|
+
it_behaves_like "um recurso consultável", "cte"
|
|
6
|
+
it_behaves_like "um recurso cancelável", "cte"
|
|
7
|
+
it_behaves_like "um recurso corrigível por campo", "cte"
|
|
8
|
+
it_behaves_like "um recurso notificável", "cte"
|
|
9
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::CtesRecebidas do
|
|
4
|
+
include_context "com recurso conectado"
|
|
5
|
+
|
|
6
|
+
let(:chave) { "35200114200166000187570010000000201234567890" }
|
|
7
|
+
|
|
8
|
+
it_behaves_like "um recurso listável", "ctes_recebidas"
|
|
9
|
+
it_behaves_like "um recurso baixável", "ctes_recebidas"
|
|
10
|
+
it_behaves_like "um recurso notificável", "ctes_recebidas"
|
|
11
|
+
|
|
12
|
+
describe "#consultar" do
|
|
13
|
+
it "faz GET em /v2/ctes_recebidas/{chave} e devolve o corpo cru" do
|
|
14
|
+
stub_get("ctes_recebidas/#{chave}", body: '{"situacao":"autorizado"}')
|
|
15
|
+
|
|
16
|
+
expect(recurso.consultar(chave)).to eq("situacao" => "autorizado")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#desacordo" do
|
|
21
|
+
it "faz POST em /{chave}/desacordo com as observações" do
|
|
22
|
+
corpo = '{"observacoes":"Mercadoria não recebida conforme."}'
|
|
23
|
+
stub = stub_envio(:post, "ctes_recebidas/#{chave}/desacordo", body: corpo)
|
|
24
|
+
|
|
25
|
+
recurso.desacordo(chave, observacoes: "Mercadoria não recebida conforme.")
|
|
26
|
+
|
|
27
|
+
expect(stub).to have_been_requested
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "#consultar_desacordo" do
|
|
32
|
+
it "faz GET em /{chave}/desacordo e devolve o corpo cru" do
|
|
33
|
+
stub_get("ctes_recebidas/#{chave}/desacordo", body: '{"status":"registrado"}')
|
|
34
|
+
|
|
35
|
+
expect(recurso.consultar_desacordo(chave)).to eq("status" => "registrado")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "#download_xml_cancelamento" do
|
|
40
|
+
it "faz GET em /{chave}/cancelamento.xml e devolve o XML cru" do
|
|
41
|
+
stub_get("ctes_recebidas/#{chave}/cancelamento.xml",
|
|
42
|
+
body: "<procEventoCTe/>", headers: { "Content-Type" => "application/xml" })
|
|
43
|
+
|
|
44
|
+
expect(recurso.download_xml_cancelamento(chave)).to eq("<procEventoCTe/>")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "#download_xml_carta_correcao" do
|
|
49
|
+
it "faz GET em /{chave}/carta_correcao.xml e devolve o XML cru" do
|
|
50
|
+
stub_get("ctes_recebidas/#{chave}/carta_correcao.xml",
|
|
51
|
+
body: "<procEventoCTe/>", headers: { "Content-Type" => "application/xml" })
|
|
52
|
+
|
|
53
|
+
expect(recurso.download_xml_carta_correcao(chave)).to eq("<procEventoCTe/>")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Dce do
|
|
4
|
+
it_behaves_like "um recurso emitível", "dce"
|
|
5
|
+
it_behaves_like "um recurso consultável", "dce"
|
|
6
|
+
it_behaves_like "um recurso cancelável", "dce"
|
|
7
|
+
it_behaves_like "um recurso notificável", "dce"
|
|
8
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::EmailsBloqueados do
|
|
4
|
+
include_context "com recurso conectado"
|
|
5
|
+
|
|
6
|
+
let(:email) { "bloqueado@exemplo.com" }
|
|
7
|
+
|
|
8
|
+
it "usa o caminho_base 'blocked_emails'" do
|
|
9
|
+
expect(recurso.caminho_base).to eq("blocked_emails")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#consultar" do
|
|
13
|
+
it "faz GET em /v2/blocked_emails/{email} e devolve o corpo cru" do
|
|
14
|
+
stub_get("blocked_emails/#{email}", body: '{"block_type":"bounce"}')
|
|
15
|
+
|
|
16
|
+
expect(recurso.consultar(email)).to eq("block_type" => "bounce")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#desbloquear" do
|
|
21
|
+
it "faz DELETE em /v2/blocked_emails/{email}" do
|
|
22
|
+
stub = stub_envio(:delete, "blocked_emails/#{email}")
|
|
23
|
+
|
|
24
|
+
recurso.desbloquear(email)
|
|
25
|
+
|
|
26
|
+
expect(stub).to have_been_requested
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe FocusNfe::Recursos::Empresas do
|
|
4
|
+
include_context "com recurso conectado"
|
|
5
|
+
|
|
6
|
+
let(:dados) { { "nome" => "Loja", "cnpj" => "12345678000123" } }
|
|
7
|
+
|
|
8
|
+
it_behaves_like "um recurso listável", "empresas"
|
|
9
|
+
it_behaves_like "um recurso localizável", "empresas"
|
|
10
|
+
it_behaves_like "um recurso removível", "empresas"
|
|
11
|
+
|
|
12
|
+
describe "#criar" do
|
|
13
|
+
it "faz POST em /v2/empresas com os dados e devolve o corpo cru" do
|
|
14
|
+
stub_envio(:post, "empresas", body: JSON.generate(dados), resposta: '{"id":1}')
|
|
15
|
+
|
|
16
|
+
expect(recurso.criar(dados: dados)).to eq("id" => 1)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "inclui dry_run=1 na query quando dry_run: true" do
|
|
20
|
+
stub = stub_envio(:post, "empresas", query: { dry_run: 1 }, body: JSON.generate(dados))
|
|
21
|
+
|
|
22
|
+
recurso.criar(dados: dados, dry_run: true)
|
|
23
|
+
|
|
24
|
+
expect(stub).to have_been_requested
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "não envia dry_run por padrão" do
|
|
28
|
+
stub = stub_envio(:post, "empresas", body: JSON.generate(dados))
|
|
29
|
+
|
|
30
|
+
recurso.criar(dados: dados)
|
|
31
|
+
|
|
32
|
+
expect(stub).to have_been_requested
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#atualizar" do
|
|
37
|
+
it "faz PUT em /v2/empresas/{id} com os dados" do
|
|
38
|
+
stub = stub_envio(:put, "empresas/7", body: JSON.generate(dados))
|
|
39
|
+
|
|
40
|
+
recurso.atualizar("7", dados: dados)
|
|
41
|
+
|
|
42
|
+
expect(stub).to have_been_requested
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|