Cada decisão tomada com base no que ele aprendeu passa a ser guardada com o motivo (aprendizado.decidir, até 800, persistidas): - acordou do cochilo antes da hora: "às 18h de quarta costuma ter gente, pelo plano que você contou"; - cochilo com a casa vazia, com a duração e o porquê; - sensor segurado numa hora em que acordou à toa (no máximo 1 nota a cada 10 min); - gesto escolhido porque costuma agradar (chance ≥ ×1,3); - fechamento do dia: horas com gente, carinhos e quanto o dia conferiu com o plano; - análise da IA (adotada ou sugestão, com a porcentagem) e rotina contada por você. esperado_e_fonte diz de onde veio a expectativa (plano seu, plano da IA, o que viu naquele dia da semana ou média). GET /aprendizado/dia devolve um dia: medido × plano por hora, conferência do dia, resumo e decisões. Painel: tela "Dia a dia" (#/dia-a-dia) com navegação entre dias, os números do dia, as faixas "Viu" × "Esperava" e a linha do tempo das decisões; atalho no cartão "O que ele aprendeu", no Ctrl+K e no guia. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
432 lines
20 KiB
Python
432 lines
20 KiB
Python
"""Aprendizado com o dia a dia: gosto pelos atos, rotina da casa, sono e o fechamento do dia."""
|
|
import http.client
|
|
import importlib.util
|
|
import json
|
|
import random
|
|
import sys
|
|
import tempfile
|
|
import threading
|
|
import time
|
|
import unittest
|
|
from datetime import date, timedelta
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT))
|
|
from aprendizado import Aprendizado # noqa: E402
|
|
from vida import Vida # noqa: E402
|
|
|
|
spec = importlib.util.spec_from_file_location('kiosk_aprendizado', ROOT / 'kiosk-server.py')
|
|
kiosk = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(kiosk)
|
|
|
|
|
|
def em(dia, hora, minuto=0, segundo=0):
|
|
return time.mktime((2026, 10, dia, hora, minuto, segundo, 0, 0, -1))
|
|
|
|
|
|
class AprendizadoTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmp = tempfile.TemporaryDirectory()
|
|
self.caminho = Path(self.tmp.name) / 'aprendizado.json'
|
|
self.a = Aprendizado(self.caminho)
|
|
self.a.hoje = self.a._dia_vazio('2026-10-06')
|
|
self.diario = []
|
|
self.a.anotar = lambda tipo, texto, agora=None: self.diario.append((tipo, texto))
|
|
|
|
def tearDown(self):
|
|
self.tmp.cleanup()
|
|
|
|
def fazer(self, nome, vezes, resposta=None, inicio=None):
|
|
t = inicio or em(6, 15)
|
|
for i in range(vezes):
|
|
self.a.ato(nome, t + i * 120, perto=True)
|
|
if resposta:
|
|
self.a.resposta(resposta, t + i * 120 + 20)
|
|
|
|
def test_gosto_sobe_com_carinho_e_desce_quando_ignorado(self):
|
|
self.fazer('rir', 5, 'carinho')
|
|
self.fazer('bocejar', 5, inicio=em(6, 16))
|
|
self.assertGreater(self.a.peso('rir'), 1.0)
|
|
self.assertLess(self.a.peso('bocejar'), 1.0)
|
|
self.assertLessEqual(self.a.peso('rir'), 2.0)
|
|
self.assertGreaterEqual(self.a.peso('bocejar'), 0.5)
|
|
|
|
def test_sem_opiniao_com_poucas_tentativas_ou_sozinho(self):
|
|
self.fazer('rir', 2, 'carinho')
|
|
self.assertEqual(self.a.peso('rir'), 1.0)
|
|
for i in range(10):
|
|
self.a.ato('pensar', em(6, 15) + i, perto=False) # sem plateia ninguém pode gostar
|
|
self.assertEqual(self.a.peso('pensar'), 1.0)
|
|
self.assertNotIn('pensar', self.a.itens)
|
|
|
|
def test_resposta_fora_da_janela_nao_conta(self):
|
|
for i in range(4):
|
|
self.a.ato('acenar', em(6, 15) + i * 300, perto=True)
|
|
self.a.resposta('carinho', em(6, 15) + i * 300 + 200) # 200 s depois: já era outra coisa
|
|
self.assertEqual(self.a.itens['acenar']['s'], 0)
|
|
|
|
def test_cada_ato_agrada_uma_vez(self):
|
|
self.a.ato('rir', em(6, 15), perto=True)
|
|
for _ in range(5):
|
|
self.a.resposta('carinho', em(6, 15) + 10)
|
|
self.assertEqual(self.a.itens['rir']['s'], 1.0)
|
|
|
|
def test_fechar_o_dia_gera_licoes_e_esquece_um_pouco(self):
|
|
self.fazer('rir', 4, 'carinho')
|
|
self.fazer('bocejar', 5, inicio=em(6, 17))
|
|
t_antes = self.a.itens['rir']['t']
|
|
self.a.observar(em(7, 0, 1), perto=False) # meia-noite: fecha o dia 6
|
|
textos = [t for _, t in self.diario]
|
|
self.assertTrue(any('gostam de me ver dar risada' in t for t in textos), textos)
|
|
self.assertTrue(any('Tentei bocejar 5 vezes e ninguém ligou' in t for t in textos), textos)
|
|
self.assertAlmostEqual(self.a.itens['rir']['t'], t_antes * 0.85, places=2)
|
|
self.assertEqual(self.a.hoje['dia'], '2026-10-07')
|
|
self.assertTrue(self.caminho.exists())
|
|
|
|
def test_rotina_da_casa_e_acordar_antes_de_chegarem(self):
|
|
for dia in (6, 7, 8):
|
|
for minuto in range(60):
|
|
self.a.observar(em(dia, 17, minuto), perto=False) # 17h: casa vazia
|
|
self.a.observar(em(dia, 18, minuto), perto=True) # 18h: chegou gente
|
|
self.a.observar(em(9, 0, 1), perto=False)
|
|
self.assertGreaterEqual(self.a.rotina[18], 0.5)
|
|
self.assertLess(self.a.rotina[17], 0.3)
|
|
self.assertTrue(any('costumam estar por perto das 18h às 19h' in t for _, t in self.diario), self.diario)
|
|
self.assertTrue(self.a.chega_logo(em(9, 17, 50)))
|
|
self.assertFalse(self.a.chega_logo(em(9, 17, 10))) # ainda falta muito
|
|
self.assertFalse(self.a.chega_logo(em(9, 12, 50)))
|
|
|
|
def test_acordar_a_toa_pede_mais_movimento_naquela_hora(self):
|
|
for dia in (6, 7, 8, 9):
|
|
for vez in range(2):
|
|
t = em(dia, 22, vez * 20)
|
|
self.a.acordou_pelo_sensor(t)
|
|
for s in range(0, 200, 5):
|
|
self.a.observar(t + s, perto=s < 10) # mexeu e sumiu: foi à toa
|
|
self.a.observar(em(dia + 1, 0, 1), perto=False)
|
|
self.assertGreaterEqual(self.a.extra_pir(em(10, 22, 30)), 1)
|
|
self.assertEqual(self.a.extra_pir(em(10, 15)), 0)
|
|
self.assertTrue(any('Acordei à toa 2 vezes por volta das 22h' in t for _, t in self.diario), self.diario)
|
|
|
|
def test_acordar_com_carinho_valeu_a_pena(self):
|
|
t = em(6, 22)
|
|
self.a.acordou_pelo_sensor(t)
|
|
self.a.observar(t + 5, perto=True)
|
|
self.a.resposta('carinho', t + 30)
|
|
for s in range(35, 200, 5):
|
|
self.a.observar(t + s, perto=False)
|
|
self.assertEqual(self.a.hoje['falsos'][22], 0)
|
|
|
|
def test_desligado_nao_aprende_nem_muda_nada(self):
|
|
self.a.configurar(dict(ligado=False))
|
|
self.fazer('rir', 6, 'carinho')
|
|
self.assertEqual(self.a.peso('rir'), 1.0)
|
|
self.assertEqual(self.a.extra_pir(em(6, 22)), 0)
|
|
self.assertFalse(self.a.chega_logo(em(6, 17, 50)))
|
|
|
|
def test_esquecer_e_persistencia(self):
|
|
self.fazer('rir', 5, 'carinho')
|
|
self.fazer('bocejar', 5, inicio=em(6, 17)) # o gosto é relativo: precisa de algo menos querido
|
|
self.a.salvar()
|
|
outro = Aprendizado(self.caminho)
|
|
self.assertGreater(outro.peso('rir'), 1.0)
|
|
outro.anotar = lambda *a, **k: None
|
|
outro.esquecer()
|
|
self.assertEqual(outro.peso('rir'), 1.0)
|
|
self.assertEqual(Aprendizado(self.caminho).itens, {})
|
|
|
|
def test_validar(self):
|
|
with self.assertRaises(ValueError):
|
|
self.a.configurar(dict(ligado='sim'))
|
|
with self.assertRaises(ValueError):
|
|
self.a.configurar(dict(outro=True))
|
|
|
|
|
|
class VidaComAprendizadoTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmp = tempfile.TemporaryDirectory()
|
|
self.a = Aprendizado(Path(self.tmp.name) / 'aprendizado.json')
|
|
self.a.hoje = self.a._dia_vazio('2026-10-06')
|
|
self.v = Vida(Path(self.tmp.name) / 'vida.json', iniciar=False, rng=random.Random(3))
|
|
self.v.aprendizado = self.a
|
|
self.ordens = []
|
|
self.v.enfileirar = self.ordens.append
|
|
self.v.ultimo_tick = em(6, 15)
|
|
|
|
def tearDown(self):
|
|
self.tmp.cleanup()
|
|
|
|
def test_gesto_que_agrada_sai_mais(self):
|
|
for i in range(8):
|
|
self.a.ato('rir', em(6, 15) + i * 100, perto=True)
|
|
self.a.resposta('carinho', em(6, 15) + i * 100 + 5)
|
|
self.a.ato('feliz', em(6, 15) + i * 100 + 50, perto=True)
|
|
opcoes = [('rir', 1, ''), ('feliz', 1, '')]
|
|
saiu = [self.v.escolher(opcoes)[0] for _ in range(400)]
|
|
self.assertGreater(saiu.count('rir'), saiu.count('feliz') * 2)
|
|
|
|
def test_carinho_e_atos_com_plateia_chegam_ao_aprendizado(self):
|
|
self.v.alguem_perto = lambda: True
|
|
self.v.celular_online = lambda: True
|
|
self.v.proximo_ato = 0
|
|
self.v.necessidades.update(energia=90, social=90, diversao=90, alegria=90)
|
|
ato = None
|
|
for i in range(30):
|
|
ato = self.v.tick(em(6, 15) + i * 200)
|
|
if ato in self.a.itens:
|
|
break
|
|
self.assertIn(ato, self.a.itens)
|
|
self.v.estimulo('carinho', em(6, 15) + i * 200 + 10)
|
|
self.assertGreater(self.a.itens[ato]['s'], 0)
|
|
|
|
def test_pir_pede_mais_quando_acordou_a_toa_naquela_hora(self):
|
|
self.a.falsos[22] = 1.0
|
|
self.assertFalse(self.v.pir_acorda(em(6, 22)))
|
|
self.assertTrue(self.v.pir_acorda(em(6, 22) + 10))
|
|
self.assertEqual(self.a.acordou_em, em(6, 22) + 10)
|
|
self.assertTrue(self.v.pir_acorda(em(6, 15)))
|
|
|
|
def test_acorda_do_cochilo_antes_de_chegarem(self):
|
|
self.a.rotina[18], self.a.rotina[17] = 0.8, 0.1
|
|
self.v.dormindo_proprio = True
|
|
self.v.necessidades['energia'] = 70
|
|
self.assertEqual(self.v.agir(em(6, 17, 50)), 'acordar')
|
|
self.assertIn('acordar', self.ordens)
|
|
|
|
def test_sono_profundo_nao_e_interrompido_pela_rotina(self):
|
|
self.a.rotina[18], self.a.rotina[17] = 0.8, 0.1
|
|
self.v.dormindo_proprio = True
|
|
self.v.sono_profundo = True
|
|
self.v.necessidades['energia'] = 70
|
|
self.assertIsNone(self.v.agir(em(6, 17, 50)))
|
|
|
|
|
|
def semana_tipica(a, semanas=2):
|
|
"""Segunda, sexta e fim de semana em casa (7h-23h); terça a quinta fora das 8h às 18h. Começa em 05/10 (segunda)."""
|
|
inicio = date(2026, 10, 5)
|
|
for i in range(semanas * 7):
|
|
d = inicio + timedelta(days=i)
|
|
a.hoje = a._dia_vazio(d.isoformat())
|
|
for h in range(24):
|
|
for m in range(0, 60, 2):
|
|
fora = d.weekday() in (1, 2, 3) and 8 <= h < 18
|
|
perto = 7 <= h < 23 and not fora and m < 40
|
|
a.minuto = None
|
|
a.observar(time.mktime((d.year, d.month, d.day, h, m, 0, 0, 0, -1)), perto)
|
|
fim = d + timedelta(days=1)
|
|
a.observar(time.mktime((fim.year, fim.month, fim.day, 0, 0, 30, 0, 0, -1)), False)
|
|
|
|
|
|
def plano_certo():
|
|
dias = []
|
|
for dia in range(7):
|
|
if dia in (1, 2, 3):
|
|
periodos = [dict(ini=0, fim=7, tipo='dormindo'), dict(ini=7, fim=8, tipo='casa'),
|
|
dict(ini=8, fim=18, tipo='fora'), dict(ini=18, fim=23, tipo='casa'), dict(ini=23, fim=24, tipo='dormindo')]
|
|
else:
|
|
periodos = [dict(ini=0, fim=7, tipo='dormindo'), dict(ini=7, fim=23, tipo='casa'), dict(ini=23, fim=24, tipo='dormindo')]
|
|
dias.append(dict(dia=dia, periodos=periodos))
|
|
return dict(padroes=['Percebi que de terça a quinta a casa fica vazia das 8h às 18h'], dias=dias)
|
|
|
|
|
|
class SemanaTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmp = tempfile.TemporaryDirectory()
|
|
self.a = Aprendizado(Path(self.tmp.name) / 'ap.json')
|
|
self.diario = []
|
|
self.a.anotar = lambda tipo, texto, agora=None: self.diario.append(texto)
|
|
self.pedidos = []
|
|
self.resposta = plano_certo()
|
|
|
|
def ia(provedor, prompt, schema):
|
|
self.pedidos.append((provedor, prompt))
|
|
return self.resposta
|
|
self.a.ia, self.a.pode_ia = ia, lambda provedor: True
|
|
self.a.config['analise_ia'] = False # nos testes a análise é chamada direto
|
|
|
|
def tearDown(self):
|
|
self.tmp.cleanup()
|
|
|
|
def test_quadro_da_semana_separa_os_dias(self):
|
|
semana_tipica(self.a)
|
|
self.assertEqual(len(self.a.historico), 14)
|
|
self.assertLess(self.a.semana[2][10], 0.3) # quarta 10h: fora
|
|
self.assertGreater(self.a.semana[0][10], 0.5) # segunda 10h: em casa
|
|
self.assertGreater(self.a.semana[4][10], 0.5) # sexta 10h: em casa
|
|
self.assertEqual(self.a.esperado(em(14, 10)), 'fora') # 14/10 é quarta
|
|
self.assertEqual(self.a.esperado(em(12, 10)), 'casa') # 12/10 é segunda
|
|
self.assertTrue(self.a.chega_logo(em(14, 17, 50))) # quarta: chegam às 18h
|
|
self.assertFalse(self.a.chega_logo(em(12, 17, 50))) # segunda: já tem gente em casa
|
|
self.assertTrue(self.a.casa_vazia(em(14, 10)))
|
|
|
|
def test_plano_da_ia_que_bate_com_os_dados_e_usado(self):
|
|
semana_tipica(self.a)
|
|
self.a.analisar(em(19, 1))
|
|
self.assertIn('quarta', self.pedidos[0][1])
|
|
self.assertIn('sexta (2 dias medidos)', self.pedidos[0][1])
|
|
self.assertEqual(self.a.plano['origem'], 'ia')
|
|
self.assertGreaterEqual(self.a.conferir(self.a.plano), 0.7)
|
|
self.assertIsNone(self.a.sugestao)
|
|
self.assertEqual(self.a.esperado(em(14, 10)), 'fora')
|
|
self.assertEqual(self.a.esperado(em(14, 2)), 'dormindo')
|
|
self.assertTrue(any('terça a quinta' in t for t in self.diario))
|
|
|
|
def test_plano_da_ia_que_nao_bate_vira_so_sugestao(self):
|
|
semana_tipica(self.a)
|
|
errado = plano_certo()
|
|
for d in errado['dias']:
|
|
d['periodos'] = [dict(ini=0, fim=24, tipo='fora')] # "a casa vive vazia": falso
|
|
self.resposta = errado
|
|
self.a.analisar(em(19, 1))
|
|
self.assertIsNone(self.a.plano)
|
|
self.assertIsNotNone(self.a.sugestao)
|
|
self.assertLess(self.a.conferir(self.a.sugestao), 0.7)
|
|
self.assertTrue(any(t.startswith('Acho que') for t in self.diario))
|
|
self.a.usar_sugestao()
|
|
self.assertEqual(self.a.plano['origem'], 'voce')
|
|
|
|
def test_rotina_contada_vale_na_hora_e_a_ia_nao_atropela(self):
|
|
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
|
|
self.assertIn('Fico fora de terça a quinta', self.pedidos[0][1])
|
|
self.assertEqual(self.a.plano['origem'], 'voce')
|
|
self.assertIsNone(self.a.conferir(self.a.plano)) # ainda sem dados para conferir
|
|
semana_tipica(self.a)
|
|
self.assertGreaterEqual(self.a.conferir(self.a.plano), 0.7)
|
|
self.a.analisar(em(19, 1))
|
|
self.assertEqual(self.a.plano['origem'], 'voce') # o que a pessoa disse continua valendo
|
|
self.assertIsNotNone(self.a.sugestao)
|
|
|
|
def test_validar_plano_conserta_o_que_a_ia_erra(self):
|
|
p = Aprendizado.validar_plano(dict(padroes=['ok'] * 9, dias=[
|
|
dict(dia=0, periodos=[dict(ini=8, fim=20, tipo='casa'), dict(ini=18, fim=30, tipo='fora'),
|
|
dict(ini=5, fim=5, tipo='casa'), dict(ini=1, fim=3, tipo='festa')]),
|
|
dict(dia=9, periodos=[dict(ini=0, fim=24, tipo='casa')]), 'lixo']), 'ia')
|
|
self.assertEqual(p['dias'][0], [dict(ini=8, fim=18, tipo='casa'), dict(ini=18, fim=24, tipo='fora')])
|
|
self.assertEqual(len(p['padroes']), 5)
|
|
with self.assertRaises(ValueError):
|
|
Aprendizado.validar_plano(dict(padroes=[], dias=[]), 'ia')
|
|
|
|
def test_analise_roda_sozinha_a_meia_noite_com_uma_semana(self):
|
|
self.a.config['analise_ia'] = True
|
|
semana_tipica(self.a, semanas=1)
|
|
for _ in range(50):
|
|
if not self.a.analise['ocupado'] and (self.a.plano or self.a.sugestao):
|
|
break
|
|
time.sleep(0.05)
|
|
self.assertEqual(len(self.pedidos), 1) # só na 7ª meia-noite
|
|
self.assertIsNotNone(self.a.plano or self.a.sugestao)
|
|
|
|
def test_persistencia_da_semana_e_do_plano(self):
|
|
semana_tipica(self.a, semanas=1)
|
|
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
|
|
self.a.salvar()
|
|
outro = Aprendizado(Path(self.tmp.name) / 'ap.json')
|
|
self.assertEqual(outro.semana, self.a.semana)
|
|
self.assertEqual(outro.plano['dias'], self.a.plano['dias'])
|
|
self.assertEqual(len(outro.historico), 7)
|
|
|
|
def test_casa_vazia_faz_ele_cochilar_para_guardar_pique(self):
|
|
v = Vida(Path(self.tmp.name) / 'v.json', iniciar=False, rng=random.Random(5))
|
|
v.aprendizado = self.a
|
|
v.enfileirar = lambda ordem: None
|
|
v.celular_online = lambda: True
|
|
v.necessidades.update(energia=70, diversao=80, social=80, alegria=80)
|
|
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
|
|
v.visto_em = em(14, 9)
|
|
atos = [v.agir(em(14, 10) + i * 120) for i in range(10)]
|
|
self.assertIn('atividade dormir', atos)
|
|
cochilo = next(d for d in self.a.decisoes if d['tipo'] == 'cochilo')
|
|
self.assertEqual(cochilo['motivo'], 'às 10h de quarta a casa costuma ficar vazia, pelo plano que você contou')
|
|
|
|
|
|
class DiaADiaTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmp = tempfile.TemporaryDirectory()
|
|
self.a = Aprendizado(Path(self.tmp.name) / 'ap.json')
|
|
self.a.ia, self.a.pode_ia = (lambda provedor, prompt, schema: plano_certo()), (lambda provedor: True)
|
|
self.a.config['analise_ia'] = False
|
|
self.v = Vida(Path(self.tmp.name) / 'v.json', iniciar=False, rng=random.Random(2))
|
|
self.v.aprendizado = self.a
|
|
self.v.enfileirar = lambda ordem: None
|
|
|
|
def tearDown(self):
|
|
self.tmp.cleanup()
|
|
|
|
def test_cada_decisao_guarda_o_porque(self):
|
|
semana_tipica(self.a)
|
|
self.a.analisar(em(19, 1))
|
|
self.assertEqual(self.a.decisoes[0]['tipo'], 'ia')
|
|
self.assertIn('plano adotado: confere', self.a.decisoes[0]['motivo'])
|
|
# acordar antes da chegada (quarta, 17h50)
|
|
self.v.dormindo_proprio = True
|
|
self.v.necessidades['energia'] = 70
|
|
self.assertEqual(self.v.agir(em(14, 17, 50)), 'acordar')
|
|
self.assertEqual(self.a.decisoes[0]['motivo'], 'às 18h de quarta costuma ter gente, pelo plano da IA')
|
|
# sensor segurado numa hora em que acordou à toa
|
|
self.a.falsos[22] = 1.0
|
|
self.v.pir_acorda(em(14, 22))
|
|
self.v.pir_acorda(em(14, 22) + 30) # a 2ª nota em menos de 10 min não repete
|
|
notas = [d for d in self.a.decisoes if d['tipo'] == 'sono']
|
|
self.assertEqual(len(notas), 1)
|
|
self.assertIn('pede 1 movimento a mais', notas[0]['motivo'])
|
|
|
|
def test_fechar_o_dia_resume_e_confere_com_o_plano(self):
|
|
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
|
|
semana_tipica(self.a, semanas=1)
|
|
fechou = [d for d in self.a.decisoes if d['tipo'] == 'dia']
|
|
self.assertEqual(len(fechou), 7)
|
|
quarta = next(d for d in fechou if 'quarta' in d['texto'])
|
|
self.assertIn('conferiu 100% com o plano', quarta['motivo'])
|
|
|
|
def test_dia_a_dia_de_um_dia_passado_e_de_hoje(self):
|
|
semana_tipica(self.a)
|
|
self.a.analisar(em(19, 1))
|
|
d = self.a.dia_a_dia('2026-10-14')
|
|
self.assertEqual(d['nome_dia'], 'quarta')
|
|
self.assertFalse(d['hoje'])
|
|
self.assertLess(d['medido'][10], 0.3)
|
|
self.assertEqual(d['plano'][2], dict(ini=8, fim=18, tipo='fora'))
|
|
self.assertEqual(d['confere'], 1.0)
|
|
self.assertTrue(any(x['tipo'] == 'dia' for x in d['decisoes']))
|
|
self.assertIn('2026-10-05', d['dias'])
|
|
hoje = self.a.dia_a_dia()
|
|
self.assertTrue(hoje['hoje'])
|
|
with self.assertRaises(ValueError):
|
|
self.a.dia_a_dia('ontem')
|
|
|
|
|
|
class RotasTest(unittest.TestCase):
|
|
def test_status_config_e_esquecer(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
kiosk.ARQUIVO_APARENCIA = str(Path(tmp) / 'a.json')
|
|
s = kiosk.Servidor(('127.0.0.1', 0), kiosk.Handler)
|
|
s.aprendizado = Aprendizado(Path(tmp) / 'ap.json')
|
|
kiosk.ligar_eventos(s)
|
|
threading.Thread(target=s.serve_forever, daemon=True).start()
|
|
try:
|
|
def pedir(metodo, rota, corpo=None):
|
|
c = http.client.HTTPConnection('127.0.0.1', s.server_port, timeout=5)
|
|
dados = json.dumps(corpo).encode() if corpo is not None else None
|
|
c.request(metodo, rota, body=dados, headers={'Content-Type': 'application/json'} if dados else {})
|
|
r = c.getresponse()
|
|
return r.status, json.loads(r.read())
|
|
cod, st = pedir('GET', '/aprendizado/status')
|
|
self.assertEqual(cod, 200)
|
|
self.assertEqual(len(st['rotina']), 24)
|
|
cod, st = pedir('POST', '/aprendizado/config', dict(ligado=False))
|
|
self.assertEqual((cod, st['config']['ligado']), (200, False))
|
|
cod, st = pedir('POST', '/aprendizado/config', dict(ligado='x'))
|
|
self.assertEqual(cod, 400)
|
|
cod, st = pedir('POST', '/aprendizado/esquecer', {})
|
|
self.assertEqual((cod, st['dias']), (200, 0))
|
|
cod, est = pedir('GET', '/estado')
|
|
self.assertIn('aprendizado', est)
|
|
finally:
|
|
s.shutdown()
|
|
kiosk.EVENTOS.fechar()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|