Adding some polls API endpoints for PR to discourse_api, which work fine. Now I’m trying to understand how to create tests before submitting the PR, e.g.:
require 'spec_helper'
describe DiscourseApi::API::Polls do
subject { DiscourseApi::Client.new("http://localhost:3000", "test_d7fd0429940", "test_user" )}
describe "#polls" do
before do
stub_get("http://localhost:3000/polls/voters.json").to_return(body: fixture("voters.json"), headers: { content_type: "application/json" })
end
it "requests the correct resource" do
subject.voters :post_id => 27885, :poll_name => 'poll'
expect(a_get("http://localhost:3000/polls/voters.json")).to have_been_made
end
end
end
But am getting the error:
Failed to open TCP connection to localhost:3000 (Connection refused - connect(2) for "localhost" port 3000)
# ./lib/discourse_api/client.rb:141:in `rescue in request'
# ./lib/discourse_api/client.rb:132:in `request'
# ./lib/discourse_api/client.rb:85:in `get'
# ./lib/discourse_api/api/polls.rb:22:in `voters'
# ./spec/discourse_api/api/polls_spec.rb:12:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Errno::ECONNREFUSED:
# Connection refused - connect(2) for "localhost" port 3000
# /Users/kimardenmiller/.rbenv/versions/2.5.3/gemsets/d_api/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/net_http.rb:109:in `request'
All the existing tests pass fine for me, and I’m trying to copy the format of those existing tests, but cannot for the life of me figure out what I’m doing wrong.
Here’s the (new) endpoint being tested:
module DiscourseApi
module API
module Polls
def poll_voters(args)
args = API.params(args) # post_id, poll_name, user, opts = {}
.required(:post_id, :poll_name)
.optional(:opts, :api_username)
response = get("/polls/voters.json", args)
response[:body]
end
end
end
end
Have working tests, though my gut tells me I could use tips on making those urls more elegant.
require 'spec_helper'
describe DiscourseApi::API::Polls do
subject { DiscourseApi::Client.new("http://localhost:3000", "test_d7fd0429940", "test_user" )}
describe "#polls" do
before do
stub_get("http://localhost:3000/polls/voters.json?post_id=27885&poll_name=poll").to_return(body: fixture("polls_voters.json"), headers: { content_type: "application/json" })
end
it "requests the correct resource" do
subject.poll_voters post_id: 27885, poll_name: 'poll'
expect(a_get("http://localhost:3000/polls/voters.json?post_id=27885&poll_name=poll")).to have_been_made
end
it "returns the expected votes" do
voters = subject.poll_voters post_id: 27885, poll_name: 'poll'
expect(voters).to be_a Hash
voters.each { |g| expect(g).to be_an Array }
expect(voters['voters']['e539a9df8700d0d05c69356a07b768cf']).to be_an Array
expect(voters['voters']['e539a9df8700d0d05c69356a07b768cf'][0]['id']).to eq(356)
end
end
end
Glad you got the tests working. They can be tricky sometimes because if the request doesn’t match exactly it will try and create an actual request rather that using the stubbed request.
I think the urls are okay. It would be nice not to use such a high post_id, but I’m not concerned about that. And ALL the tests need to have http://localhost:3000 extracted out into a common variable, but that should probably be done in a separate commit. Whenever you are ready you can go ahead and submit a pr and I can review it.
One thing I did notice though is I that passing in the api_username as a parameter is no longer supported.
This is because the discourse_api gem now only passes in the auth via the headers, and discourse core ignores any auth credentials in the body if the header is already being used for auth.
Vamos dividir os PRs, por favor. Primeiro, vamos focar no PR da especificação e mover a variável comum para a pasta de especificação. Devemos ser capazes de adicioná-la ao arquivo de helper da especificação.
Como isso é apenas para exemplos, tudo relacionado a isso deve estar dentro do diretório de exemplos, sem editar nenhuma funcionalidade existente no diretório lib. Até mesmo o arquivo config.yml deve ser colocado dentro do diretório de exemplos. Carregar o arquivo YAML é bastante leve; podemos adicioná-lo no topo de cada arquivo de exemplo, mas provavelmente seria melhor adicioná-lo a um arquivo comum dentro do diretório de exemplos, do qual todos possam ler.
# host, por exemplo: localhost:3000 ou discourse.meudominio.com
host: SEU_NOME_DE_HOST
# usuário da API (pode afetar os resultados retornados, por exemplo, o método .categories retorna apenas as categorias que seu api_username pode ver)
# crie um novo cliente ao alterar o usuário da API
api_username: SEU_API_KEY
# chave da API do painel de administração do Discourse /admin/api/keys
api_key: SEU_API_KEY
Parece bom. Vamos atualizar o helper de exemplo com valores padrão para que ele funcione sem o arquivo yml. Em seguida, atualize o readme com instruções para copiar o arquivo yml de exemplo para examples/config.yml. E não se esqueça de adicionar examples/config.yml ao .gitignore.
Essa é uma convenção bastante padrão para que não seja fácil cometer um arquivo config.yml com credenciais de produção. E você pode editar o arquivo sem que o git o veja como uma alteração.
Tudo bem, exceto que não entendi muito bem esta parte
O example_helper.rb funciona como está assim que o config.yml existir. Queremos que ele também funcione sem um arquivo yml, mas ainda temos um arquivo yml?
Acho que esse erro está correto, pois é assim que os exemplos funcionam atualmente, e isso só ocorre nos exemplos mesmo. Se quiser, agora ou mais tarde, sempre podemos capturar a exceção e fornecer uma mensagem útil.
A seção de Testes atual está um pouco confusa para mim, pois mistura tarefas relacionadas ao discourse_api com a instalação do próprio Discourse. Por exemplo, se você tiver um servidor de staging na nuvem, não precisará instalar o Discourse localmente. O que você acha disso:
Especifique seu ambiente copiando o arquivo config-example.yml e criando um arquivo chamado config.yml com suas configurações de ambiente.
Em um arquivo de exemplo específico, comente todas as linhas, exceto os exemplos que deseja executar.
Edite o arquivo de exemplo com quaisquer parâmetros necessários, por exemplo, username.
Ao executar o arquivo, ele usará seu config.yml para chamar um método de cliente específico (por exemplo, client.badges) na sua instância do Discourse.
Testes
Para executar os testes do discourse_api em spec:
Instale o bundler no diretório do discourse_api executando gem install bundler.
Dentro do diretório do discourse_api, execute: bundle exec rspec spec/.
Para executar os testes, na verdade, não é necessário ter uma instância do Discourse em execução. Todas as requisições de teste devem ser simuladas (mockadas), e um servidor não é necessário.
Para testar os exemplos em /examples, você precisará de uma instância do Discourse em execução, instalada localmente ou na nuvem, e então:
Especifique seu ambiente copiando o arquivo config-example.yml para criar um arquivo chamado config.yml com as configurações do seu ambiente.
Em um arquivo de exemplo específico, comente todos os exemplos, exceto aqueles que deseja executar.
Edite o arquivo de exemplo com os parâmetros necessários, por exemplo, um username de destino passado para o método.
A execução do arquivo então usará as informações do seu config.yml para executar um método de cliente específico (por exemplo, client.badges) contra sua instância do Discourse.
Testes
Para executar os testes do discourse_api em spec:
Instale o bundler no diretório discourse_api, executando gem install bundler.
Dentro do diretório discourse_api, execute: bundle exec rspec spec/.