https://github.com/mtlouzada/domain-inspector
Desafio Técnico Fullstack para a empresa Umbler - Desenvolvedor C# / JavaScript - Jr
https://github.com/mtlouzada/domain-inspector
asp-net-mvc dotnet efcore fullstack-development javascript reactjs tests umbler vite
Last synced: 3 months ago
JSON representation
Desafio Técnico Fullstack para a empresa Umbler - Desenvolvedor C# / JavaScript - Jr
- Host: GitHub
- URL: https://github.com/mtlouzada/domain-inspector
- Owner: mtlouzada
- Created: 2025-08-27T17:51:54.000Z (10 months ago)
- Default Branch: master
- Last Pushed: 2025-09-18T17:42:40.000Z (9 months ago)
- Last Synced: 2025-09-18T20:14:59.739Z (9 months ago)
- Topics: asp-net-mvc, dotnet, efcore, fullstack-development, javascript, reactjs, tests, umbler, vite
- Language: C#
- Homepage:
- Size: 829 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Domain Inspector
Domain Inspector é uma API web que permite consultar e consolidar informações de DNS e WHOIS de um domínio.
O projeto foi desenvolvido com foco em separação de responsabilidades, testabilidade e integração com serviços externos, servindo como um estudo de caso prático em .NET.
Exemplo de uso: consulta de dados do domínio `example.com`
**Informações retornadas:**
- Name Servers
- Registro A (endereço IP)
- Dados de hospedagem do domínio
As informações são obtidas através de consultas a servidores DNS e ao protocolo WHOIS.
*WHOIS é um protocolo utilizado para obter informações de registro e contato associadas a domínios.*
Os dados consultados são persistidos em banco de dados e reutilizados enquanto o TTL estiver válido, evitando consultas desnecessárias e melhorando a performance da aplicação.
Tecnologias Backend utilizadas:
- C#
- Asp.Net Core
- MySQL
- Entity Framework
Tecnologias Frontend utilizadas:
- Webpack
- Babel
- ES7
Para rodar o projeto você vai precisar instalar:
- dotnet Core SDK (https://www.microsoft.com/net/download/windows dotnet Core 6.0.201 SDK)
- Um editor de código, acoselhamos o Visual Studio ou VisualStudio Code. (https://code.visualstudio.com/)
- NodeJs v17.6.0 para "buildar" o FrontEnd (https://nodejs.org/en/)
- Um banco de dados MySQL (vc pode rodar localmente ou criar um site PHP gratuitamente no app da Umbler https://app.umbler.com/ que lhe oferece o banco Mysql adicionamente)
Com as ferramentas devidamente instaladas, basta executar os seguintes comandos:
Para "buildar" o javascript basta executar:
`npm install`
`npm run build`
Para Rodar o projeto:
Execute a migration no banco mysql:
`dotnet tool update --global dotnet-ef`
`dotnet tool ef database update`
E após:
`dotnet run` (ou clique em "play" no editor do vscode)
# Objetivos:
Se você rodar o projeto e testar um domínio, verá que ele já está funcionando. Porém, queremos melhorar varios pontos deste projeto:
# FrontEnd
- Os dados retornados não estão formatados, e devem ser apresentados de uma forma legível.
- Não há validação no frontend permitindo que seja submetido uma requsição inválida para o servidor (por exemplo, um domínio sem extensão).
- Está sendo utilizado "vanilla-js" para fazer a requisição para o backend, apesar de já estar configurado o webpack. O ideal seria utilizar algum framework mais moderno como ReactJs ou Blazor.
# BackEnd
- Não há validação no backend permitindo que uma requisição inválida prossiga, o que ocasiona exceptions (erro 500).
- A complexidade ciclomática do controller está muito alta, o ideal seria utilizar uma arquitetura em camadas.
- O DomainController está retornando a própria entidade de domínio por JSON, o que faz com que propriedades como Id, Ttl e UpdatedAt sejam mandadas para o cliente web desnecessariamente. Retornar uma ViewModel (DTO) neste caso seria mais aconselhado.
# Testes
- A cobertura de testes unitários está muito baixa, e o DomainController está impossível de ser testado pois não há como "mockar" a infraestrutura.
- O Banco de dados já está sendo "mockado" graças ao InMemoryDataBase do EntityFramework, mas as consultas ao Whois e Dns não.
# Dica
- Este teste não tem "pegadinha", é algo pensado para ser simples. Aconselhamos a ler o código, e inclusive algumas dicas textuais deixadas nos testes unitários.
- Há um teste unitário que está comentado, que obrigatoriamente tem que passar.
- Diferencial: criar mais testes.
# Entrega
- Enviei o link do seu repositório com o código atualizado.
- O repositório deve estar público.
- Modifique Este readme adicionando informações sobre os motivos das mudanças realizadas.
# Modificações:
Durante o desenvolvimento e refatoração do desafio, foram realizadas as seguintes melhorias:
## 1° BackEnd

1. **Migrations**
- Criação de novas migrations, alinhada com um banco de dados local MySQL e refatoração na connectionstring.
2. **Atualização da pasta Models e impacto**
#### O que foi feito:
- Atualizado o model Domain com valores padrão e [Required] nas propriedades essenciais (Name, Ip, UpdatedAt, Ttl).
- Mantida a chave primária Id e o DbSet no DatabaseContext.
#### Impacto:
- Garante integridade e consistência dos dados no banco.
- Facilita testes unitários com dados padrão.
- Permite que DomainService e DomainController retornem informações completas sem erros de valores nulos.
1. **Refatoração do Controller (`DomainController`)**
- DomainController foi simplificado: ele apenas valida entrada e retorna HTTP adequado.
- Toda a lógica de consultas (DNS, Whois, banco de dados) foi movida para o DomainService, seguindo o padrão de separação de responsabilidades.
2. **Criação do Service (`DomainService`)**
- Criado **wrapper para o `WhoisClient`** e injeção de `ILookupClient` para permitir mock durante testes unitários.
- Alterado para retornar objetos do tipo `Domain`, mantendo a lógica de persistência e consulta ao banco de dados.
- Inclusão de **tratamento de TTL** e atualização de registros antigos no banco de dados.
3. **Criação de DTO (`DomainResultDto`)**
- Separação entre a entidade do banco (`Domain`) e os dados retornados para o front-end.
- Melhora na segurança, evitando expor dados desnecessários.
- Facilita a manipulação dos dados no frontend (Vite + React).
## 2° Frontend

> OBS: Optei por criar o front usando vite + ReactJS em uma pasta diferente, seguindo as recomendações da documentação do ASP.NET. Caso não seja comum para a equipe usar build tools como o vite, também é possível buildar o frontend dentro da pasta Views. Ajustes como esse são de rápida implementação.
1. Substituição de vanilla JS por **React + TypeScript**.
2. Consulta à API via service dedicado (`domainService.ts`).
3. Validação de entrada do usuário (domínios inválidos não são enviados).
4. Dados retornados pelo backend são
exibidos de forma legível no frontend.
> OBS: A escolha do pnpm como gerenciador de pacotes no front foi meramente perfomática, por estar lidando com uma máquina com recursos limitados.
## 3° Testes Unitários
> OBS: O testa unitário que estava comentado, não estava funcionando naquele formato. Ele dependia do WhoisClient original, que é uma classe estática e não mockável diretamente.
_Para funcionar, foi preciso:_
- Criar um wrapper/método mockável para o Whois (IWhoisClientWrapper).
- Alterar o DomainService e o DomainController para usar a interface mockável em vez da classe estática.
- Criar o teste usando Mock retornando um valor fake para o domínio.
Depois dessa refatoração, esse teste passou a funcionar, mas não é mais aquele código comentado, e sim uma versão adaptada usando o service mockado.
**Porém mesmo adaptado, ele exerce exatamente a mesma função que o teste original comentado**
---
- Configuração de **InMemoryDatabase** do Entity Framework para testar interações com o banco sem depender de um banco real.
- Criação de mocks para `IDomainService` e wrappers de Whois/DNS.
- Cobertura aumentada para cenários:
- Domínio existente no banco.
- Domínio inexistente no banco.
- Domínio inválido.
- Todos os testes unitários obrigatórios passam, garantindo estabilidade da aplicação.
## 5° Extra
- Criação de um teste unitário específico para domínio inválido, simulando a requisição de um domínio que não existe ou não é válido.
- Habilitação de **CORS** e configuração de `Swagger` para facilitar testes e documentação da API.
- Atualização de pacotes NuGet para resolver conflitos de versões do Entity Framework.
- Ajustes para compatibilidade com **.NET 6**.
---
## Como Rodar
### Backend
1. Configure a ConnectionString no `appsettings.json`.
2. Execute `dotnet build`.
3. Atualize as Migrations `dotnet ef database update`
4. Execute `dotnet run` para iniciar o servidor.
### Frontend
1. Entre na pasta `client`.
2. Execute `pnpm i`.
3. Execute `pnpm dev` para iniciar o frontend.
4. Acesse [http://localhost:5173](http://localhost:5173/) (ou porta indicada pelo Vite).
### Testes
- Execute `dotnet test` na pasta `Desafio.Umbler.Test` para rodar todos os testes unitários.
---
feito :)