Debugando um checkbox escondido na UI real do Medium
Um item pequeno do backlog: fazer a ponte de importação do Medium do blog-manager ativar o paywall do Partner Program por padrão, já que estou inscrito no programa e posts canônicos/importados são totalmente elegíveis para gerar receita. Devia ter sido um ajuste de uma linha. Virou uma tarde inteira de debug ao vivo contra uma conta real do Medium, porque o checkbox que eu precisava clicar não se comporta como um checkbox normal.
Encontrando o checkbox
O medium-bridge não fala com uma API do Medium para publicar, não existe mais nenhuma que valha a pena usar, ele controla a UI web real do Medium com Playwright, do mesmo jeito que uma pessoa clicaria pelo fluxo “Import a story”. Então “ativar o metering por padrão” significava: encontrar o elemento DOM real do toggle de paywall no painel de pré-publicação do Medium, e clicar nele antes de confirmar.
Eu não queria adivinhar um seletor a partir da documentação e torcer para que batesse com a página real, o próprio texto da UI do Medium nem bate de forma consistente com a central de ajuda deles (algumas páginas dizem “meter my story”, outras dizem “paywall your story”). Então escrevi um script pequeno de diagnóstico, copiei para dentro do container de produção rodando, e rodei contra um rascunho real para listar todos os checkboxes do painel de pré-publicação. Achei na hora: um checkbox literalmente rotulado “Paywall this story”, desmarcado por padrão. Bom, direto ao ponto.
Só que, quando tentei clicar, nada aconteceu. Ver o computed style explicou por quê: width: 0px, height: 0px, opacity: 0. O input real é invisível e de tamanho zero, sentado atrás de um toggle switch customizado que é o que realmente aparece na tela. O comportamento padrão de clique do Playwright exige que o elemento tenha uma bounding box diferente de zero antes de interagir com ele, uma checagem de segurança totalmente razoável, que existe para impedir você de clicar em algo que um usuário real nunca conseguiria ver, e exatamente a checagem que estava entre mim e esse checkbox.
O checkbox que mente sobre estar desabilitado
Depois que troquei para checar presença no DOM em vez de visibilidade, um segundo problema apareceu: o checkbox fica disabled por alguns segundos logo após a importação, e só fica habilitado quando o Medium termina alguma checagem assíncrona de elegibilidade do lado do servidor. Confirmei isso monitorando o atributo disabled em várias importações de teste reais, a janela variava de praticamente instantânea a vários segundos, nunca um atraso fixo. Um input desabilitado ignora silenciosamente chamadas de click e check, mesmo com a flag force: true do Playwright, então tentar cedo demais não dá erro, simplesmente não faz nada. Minhas primeiras rodadas de teste pareciam mostrar que o ajuste não estava funcionando, até eu perceber que estava checando antes do Medium realmente terminar de decidir se o post era elegível.
O ajuste: monitorar o atributo disabled por até 15 segundos antes de tentar qualquer coisa, e só prosseguir quando ele for liberado. Também vale registrar para quem estiver caçando bugs parecidos: em toda rodada de teste limpa, depois que acertei o polling, o checkbox se estabilizava já marcado no momento em que ficava habilitado. Ainda não sei ao certo se esse é o padrão real do Medium para contas elegíveis ou algo específico do histórico da minha conta, mas o código não presume nenhuma das duas coisas. Ele checa o estado atual e só clica se ainda estiver desmarcado, então funciona corretamente independente de qual seja o padrão real do Medium.
Verificando contra uma conta real, com cuidado
A única forma de saber se isso realmente funciona é rodar contra a sessão real e autenticada do Medium, não existe ambiente de staging para o medium-bridge, nem conta sandbox. Isso significou rodar importações reais contra posts reais do blog, o que cria rascunhos reais (inofensivos, mas reais e deletáveis), e eventualmente uma publicação real para confirmar que a configuração de metering realmente entrou em vigor numa história ao vivo.
Fiz questão de manter cada etapa o menor e mais reversível possível: primeiro só importação (cria um rascunho, sem publicar), abrir o painel de pré-publicação e capturar seu estado sem nunca clicar em confirmar, e só rodar uma publicação completa quando eu estivesse confiante de que a lógica estava certa. Quando publiquei de fato, busquei a página da história ao vivo depois e procurei pelo próprio selo “Member-only story” do Medium, confirmação real, externa, e definitiva, em vez de confiar na saída de log do meu próprio código.
Também me peguei duas vezes prestes a usar uma ferramenta mais invasiva do que a que eu tinha decidido que essa tarefa merecia, mesma ação de fundo, com um wrapper ligeiramente diferente na segunda vez. Vale nomear isso: “deixa eu só ajustar os parâmetros e tentar de novo” é exatamente o instinto que transforma uma abordagem razoável em contornar um limite que você acabou de estabelecer para si mesmo. Parar e reconsiderar com clareza foi a decisão certa nas duas vezes.
O que a revisão automatizada pegou
Depois que o caminho feliz funcionou, rodei isso pela mesma passada de revisão que uso em PRs normais. Três ângulos de revisão independentes sinalizaram os mesmos dois bugs, o que é um bom sinal de que eram reais: um waitFor que nunca conseguiria rodar de fato porque uma checagem count() anterior já teria retornado antes, e um clique de fallback que podia desfazer um checkbox que na verdade já tinha sido marcado com sucesso (o check() do Playwright clica e depois, separadamente, confirma o resultado, ele pode lançar exceção nessa confirmação mesmo quando o clique em si funcionou, e minha lógica de fallback não considerava isso). Os dois são o tipo de coisa fácil de passar batido lendo o próprio código uma vez só, porque o caminho feliz esconde tudo isso completamente.
O que vem a seguir
Nada pendente, isso já está implantado e verificado. Deixei seis rascunhos descartáveis parados na conta do Medium por causa dos testes, que não consegui limpar automaticamente (meus palpites de seletor para o menu de deletar rascunho do Medium não acertaram, e não valia a pena mais interação com a produção ao vivo para resolver uma tarefa de limpeza puramente cosmética). Deleção manual quando for conveniente.
Leitura relacionada
O Medium ficava descartando minha imagem de capa, então a bridge agora cola ela direto
Duas teorias derrubadas com uma importação manual cada, um paste que salvou as dimensões mas não o src, e o caminho do seletor de arquivo nativo que finalmente anexou a imagem.
Um toggle por blog, e quando não "corrigir" um bug
Um booleano atravessando quatro camadas, e três passadas de revisão independentes concordando com um achado que eu deliberadamente não corrigi - porque o cache é o mecanismo de dedup.
O blog que não conseguia publicar num cronograma
Um design de pipeline em lote que começou com uma checagem de cinco minutos na base do sistema: posts com data futura não ficavam escondidos, viravam 404, e nada nunca reconstruía o site.
Você também pode achar útil
Proton Mail
E-mail criptografado de ponta a ponta, com arquitetura de acesso zero.
Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).
Saiba maiseSIM Airalo
eSIM de dados local para viagens - sem necessidade de trocar um SIM físico.
Este é meu link de indicação da Airalo. Você recebe um desconto no seu primeiro eSIM e eu ganho crédito da Airalo para o meu.
Saiba maisProton Pass
Gerenciador de senhas focado em privacidade, da equipe por trás do Proton Mail.
Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).
Saiba mais