Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configuracao.delprops
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ liquido.roteador.cookieParser = verdadeiro
liquido.roteador.passport = falso
liquido.roteador.json = verdadeiro
liquido.roteador.helmet = verdadeiro
liquido.roteador.porta = 3000

// Configuração de bases de dados
liquido.dados.lincones.tecnologia = 'sqlite'
Expand Down
5 changes: 5 additions & 0 deletions fontes/delprops/roteador.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ const roteador: DefinicaoPropriedade[] = [
tipo: 'logico',
detalhe: 'Habilita o helmet para segurança de cabeçalhos HTTP (padrão: verdadeiro).',
},
{
nome: 'porta',
tipo: 'numero',
detalhe: 'Porta na qual o servidor irá subir (padrão: 3000).',
}
];

export default roteador;
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { ConfiguracaoComum } from "./configuracao-comum";
export class ConfiguracaoRoteador extends ConfiguracaoComum {
diretorioEstatico: string = 'publico';
cors: boolean = false;
origensCors: string = '*';
origensCors: string | string[] = '*';
bodyParser: boolean = true;
morgan: boolean = false;
cookieParser: boolean = true;
passport: boolean = false;
json: boolean = true;
helmet: boolean = true;

porta: number = 3000;
constructor(valoresIniciais?: Partial<ConfiguracaoRoteador>) {
super();
Object.assign(this, valoresIniciais);
Expand All @@ -27,6 +27,7 @@ export class ConfiguracaoRoteador extends ConfiguracaoComum {
roteador.ativarDesativarHelmet(this.helmet);
roteador.ativarDesativarMorgan(this.morgan);
roteador.ativarDesativarPassport(this.passport);
roteador.configurarPorta(this.porta);
// Nota: configurarArquivosEstaticos é chamado em liquido.ts com caminho absoluto
}
}
34 changes: 20 additions & 14 deletions fontes/infraestrutura/roteador/roteador.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ export class Roteador implements RoteadorInterface {
bodyParser = false;

cors = false;
origensCors = '*';
origensCors: string[] = ['*'];
passport = false;

constructor(autoDocumentador: AutoDocumentador) {
this.aplicacao = express();
this.porta = Number(process.env.PORTA) || Number(process.env.PORT) || 3000;
this.porta = 3000;

this.autoDocumentador = autoDocumentador;

Expand Down Expand Up @@ -91,6 +91,10 @@ export class Roteador implements RoteadorInterface {
})
);
}
configurarPorta(porta: number): void {
this.porta = porta;

}

configurarArquivosEstaticos(diretorio: string = 'publico'): void {
this.aplicacao.use(express.static(diretorio, { redirect: true }));
Expand Down Expand Up @@ -135,7 +139,6 @@ export class Roteador implements RoteadorInterface {
this.aplicacao.use(cors(opcoesCors));
}
}

if (this.passport) {
try {
this.aplicacao.use(autenticacao().initialize());
Expand All @@ -154,8 +157,14 @@ export class Roteador implements RoteadorInterface {
* ou várias separadas por vírgula. O valor '*' (padrão) libera qualquer
* origem e deve ser usado apenas em desenvolvimento.
*/
configurarOrigensCors(origem: string): void {
this.origensCors = origem && origem.trim().length > 0 ? origem : '*';
configurarOrigensCors(origem: string | string[]): void {
if (Array.isArray(origem)) {
this.origensCors = origem;
return;
}

this.origensCors = origem.split(',').
map(origem => origem.trim()).filter(origem => origem.length > 0);
}

/**
Expand All @@ -165,20 +174,17 @@ export class Roteador implements RoteadorInterface {
* lista de origens permitidas.
*/
resolverOpcoesCors(): { origin: string[] } | undefined {
if (this.origensCors === '*') {

if (Array.isArray(this.origensCors)
&& this.origensCors.length === 1
&& this.origensCors[0] === '*') {
return undefined;
}

const origens = this.origensCors
.split(',')
.map(origem => origem.trim())
.filter(origem => origem.length > 0);

if (origens.length === 0) {
if (this.origensCors.length === 0) {
return undefined;
}

return { origin: origens };
return { origin: this.origensCors };
}

ativarDesativarPassport(valor: boolean): void {
Expand Down
3 changes: 2 additions & 1 deletion fontes/interfaces/roteador-interface.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
export interface RoteadorInterface {
ativarDesativarCors(valor: boolean): void;
configurarOrigensCors(origem: string): void;
configurarOrigensCors(origem: string | string[]): void;
ativarDesativarPassport(valor: boolean): void;
ativarDesativarCookieParser(valor: boolean): void;
ativarDesativarExpressJson(valor: boolean): void;
ativarDesativarBodyParser(valor: boolean): void;
ativarDesativarHelmet(valor: boolean): void;
ativarDesativarMorgan(valor: boolean): void;
configurarArquivosEstaticos(diretorio: string): void;
configurarPorta(porta: number): void;
}
19 changes: 16 additions & 3 deletions testes/infraestrutura/centro-configuracoes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ describe('Testes das classes de configuração', () => {
ativarDesativarHelmet: jest.fn(),
ativarDesativarMorgan: jest.fn(),
ativarDesativarPassport: jest.fn(),
configurarArquivosEstaticos: jest.fn()
configurarArquivosEstaticos: jest.fn(),
configurarPorta: jest.fn()
};
config.configurar({ roteador });
expect(roteador.ativarDesativarBodyParser).toHaveBeenCalledWith(true);
Expand All @@ -191,10 +192,14 @@ describe('Testes das classes de configuração', () => {
expect(roteador.ativarDesativarHelmet).toHaveBeenCalledWith(true);
expect(roteador.ativarDesativarMorgan).toHaveBeenCalledWith(false);
expect(roteador.ativarDesativarPassport).toHaveBeenCalledWith(false);
expect(roteador.configurarOrigensCors).toHaveBeenCalledWith('*');
expect(roteador.configurarPorta).toHaveBeenCalledWith(3000);
// configurarArquivosEstaticos agora é chamado em liquido.ts com caminho absoluto
expect(roteador.configurarArquivosEstaticos).not.toHaveBeenCalled();
});



it('não deve chamar configurarArquivosEstaticos quando diretorioEstatico for vazio', () => {
const config = new ConfiguracaoRoteador({ diretorioEstatico: '' });
const roteador = {
Expand All @@ -206,7 +211,8 @@ describe('Testes das classes de configuração', () => {
ativarDesativarHelmet: jest.fn(),
ativarDesativarMorgan: jest.fn(),
ativarDesativarPassport: jest.fn(),
configurarArquivosEstaticos: jest.fn()
configurarArquivosEstaticos: jest.fn(),
configurarPorta: jest.fn()
};
config.configurar({ roteador });
expect(roteador.configurarArquivosEstaticos).not.toHaveBeenCalled();
Expand Down Expand Up @@ -291,7 +297,8 @@ describe('Testes das classes de configuração', () => {
ativarDesativarHelmet: jest.fn(),
ativarDesativarMorgan: jest.fn(),
ativarDesativarPassport: jest.fn(),
configurarArquivosEstaticos: jest.fn()
configurarArquivosEstaticos: jest.fn(),
configurarPorta: jest.fn()
};
const provedorLincones = { configurar: jest.fn(), configurado: false, resolver: jest.fn() };
config.configurar({ autoDocumentador, roteador, provedorLincones });
Expand All @@ -318,6 +325,12 @@ describe('Testes das classes de configuração', () => {
expect(config.roteador.cors).toBe(true);
});

it('deve aceitar porta via definirValor em roteador', () => {
const config = new ConfiguracaoLiquido();
config.definirValor(config, ['liquido', 'roteador', 'porta'], 4000);
expect(config.roteador.porta).toBe(4000);
});

it('deve lançar ErroConfiguracao para propriedade aninhada inexistente', () => {
const config = new ConfiguracaoLiquido();
expect(() => config.definirValor(config, ['liquido', 'propriedadeInexistente', 'cors'], true)).toThrow(ErroConfiguracao);
Expand Down
3 changes: 2 additions & 1 deletion testes/infraestrutura/cors-origem.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ describe('CORS com origem configurável', () => {
ativarDesativarExpressJson: jest.fn(),
ativarDesativarHelmet: jest.fn(),
ativarDesativarMorgan: jest.fn(),
ativarDesativarPassport: jest.fn()
ativarDesativarPassport: jest.fn(),
configurarPorta: jest.fn(),
};

configuracao.configurar({ roteador: roteadorSimulado });
Expand Down
10 changes: 10 additions & 0 deletions testes/infraestrutura/roteador.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ describe('Testes do roteador', () => {
expect(roteador).toBeTruthy();
});

it('deve ignorar a porta do ambiente e usar o valor padrão até que a configuração seja aplicada', () => {
process.env.PORT = '4000';

const roteadorSemConfiguracao = new Roteador(new AutoDocumentador());

expect(roteadorSemConfiguracao.porta).toBe(3000);

delete process.env.PORT;
});

it('deve chamar o método iniciar', () => {
roteador.iniciar();
expect(roteador.aplicacao.listen).toHaveBeenCalled();
Expand Down
Loading