The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Human-Like Interface Testing - Dungeon Keeper",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 */2 * * *"
}
]
}
},
"id": "schedule-trigger",
"name": "Schedule Every 2 Hours",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"url": "http://localhost:3001",
"options": {
"waitUntil": "networkidle",
"timeout": 30000
}
},
"id": "open-frontend",
"name": "\ud83c\udf10 Open Frontend",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
460,
300
]
},
{
"parameters": {
"selector": "input[type='email'], input[name='email'], #email",
"action": "type",
"text": "teste_ui_{{ $now.format('HHmmss') }}@rpg.com"
},
"id": "fill-email",
"name": "\u270d\ufe0f Fill Email Field",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
680,
200
]
},
{
"parameters": {
"selector": "input[type='password'], input[name='password'], #password",
"action": "type",
"text": "senha123"
},
"id": "fill-password",
"name": "\ud83d\udd12 Fill Password Field",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
680,
320
]
},
{
"parameters": {
"selector": "input[name='username'], #username",
"action": "type",
"text": "usuario_ui_{{ $now.format('HHmmss') }}"
},
"id": "fill-username",
"name": "\ud83d\udc64 Fill Username Field",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
680,
440
]
},
{
"parameters": {
"selector": "button[type='submit'], .register-btn, #register, .btn-register",
"action": "click",
"waitForSelector": ".success-message, .dashboard, .home"
},
"id": "click-register",
"name": "\ud83c\udfaf Click Register Button",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
900,
300
]
},
{
"parameters": {
"selector": ".character-create, .new-character, #create-character",
"action": "click",
"waitForSelector": ".character-form, .character-creation"
},
"id": "navigate-character-creation",
"name": "\ud83c\udfad Navigate to Character Creation",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
1120,
300
]
},
{
"parameters": {
"jsCode": "// Simula cria\u00e7\u00e3o de m\u00faltiplos personagens como um usu\u00e1rio real\nconst characters = [\n {\n name: 'Aragorn_UI_' + new Date().getTime(),\n race: 'Humano',\n class: 'Ranger',\n level: 5\n },\n {\n name: 'Legolas_UI_' + new Date().getTime(),\n race: 'Elfo',\n class: 'Arqueiro',\n level: 4\n },\n {\n name: 'Gimli_UI_' + new Date().getTime(),\n race: 'An\u00e3o',\n class: 'Guerreiro',\n level: 6\n }\n];\n\nconst results = [];\n\nfor (const char of characters) {\n try {\n // Simula preenchimento de formul\u00e1rio como usu\u00e1rio\n await page.waitForSelector('input[name=\"name\"], #character-name');\n await page.type('input[name=\"name\"], #character-name', char.name);\n \n // Simula sele\u00e7\u00e3o de ra\u00e7a\n await page.select('select[name=\"race\"], #race', char.race);\n \n // Simula sele\u00e7\u00e3o de classe\n await page.select('select[name=\"class\"], #character-class', char.class);\n \n // Simula preenchimento de n\u00edvel\n await page.type('input[name=\"level\"], #level', char.level.toString());\n \n // Simula clique no bot\u00e3o de criar\n await page.click('button[type=\"submit\"], .create-character-btn');\n \n // Aguarda confirma\u00e7\u00e3o visual\n await page.waitForSelector('.success-message, .character-created', { timeout: 5000 });\n \n results.push({\n character: char.name,\n status: 'created',\n timestamp: new Date().toISOString()\n });\n \n // Simula tempo de usu\u00e1rio pensando\n await page.waitForTimeout(2000);\n \n } catch (error) {\n results.push({\n character: char.name,\n status: 'failed',\n error: error.message,\n timestamp: new Date().toISOString()\n });\n }\n}\n\nreturn results;"
},
"id": "create-characters-ui",
"name": "\ud83c\udfad Create Characters via UI",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1340,
300
]
},
{
"parameters": {
"selector": ".tables, .game-tables, #tables-section",
"action": "click",
"waitForSelector": ".table-list, .tables-container"
},
"id": "navigate-tables",
"name": "\ud83c\udfb2 Navigate to Tables",
"type": "n8n-nodes-base.puppeteer",
"typeVersion": 1,
"position": [
1560,
300
]
},
{
"parameters": {
"jsCode": "// Simula cria\u00e7\u00e3o de mesa como mestre\ntry {\n // Clica em criar nova mesa\n await page.click('.create-table, .new-table, #create-table');\n await page.waitForSelector('.table-form, .table-creation');\n \n // Preenche t\u00edtulo da mesa\n const tableTitle = 'Mesa \u00c9pica UI ' + new Date().getTime();\n await page.type('input[name=\"title\"], #table-title', tableTitle);\n \n // Preenche descri\u00e7\u00e3o\n const description = 'Mesa criada via automa\u00e7\u00e3o de interface para testes de usabilidade';\n await page.type('textarea[name=\"description\"], #table-description', description);\n \n // Simula sele\u00e7\u00e3o de hist\u00f3ria (se dispon\u00edvel)\n const storySelect = await page.$('select[name=\"story\"], #story-select');\n if (storySelect) {\n const options = await page.$$eval('select[name=\"story\"] option, #story-select option', opts => \n opts.map(opt => opt.value).filter(val => val && val !== '')\n );\n if (options.length > 0) {\n await page.select('select[name=\"story\"], #story-select', options[0]);\n }\n }\n \n // Clica em criar mesa\n await page.click('button[type=\"submit\"], .create-table-btn');\n \n // Aguarda confirma\u00e7\u00e3o\n await page.waitForSelector('.success-message, .table-created', { timeout: 5000 });\n \n return {\n table: tableTitle,\n status: 'created',\n timestamp: new Date().toISOString()\n };\n \n} catch (error) {\n return {\n table: 'Mesa UI Test',\n status: 'failed',\n error: error.message,\n timestamp: new Date().toISOString()\n };\n}"
},
"id": "create-table-ui",
"name": "\ud83c\udfb2 Create Table via UI",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1780,
300
]
},
{
"parameters": {
"jsCode": "// Simula navega\u00e7\u00e3o e intera\u00e7\u00e3o como jogador\nconst interactions = [];\n\ntry {\n // Simula busca por mesas dispon\u00edveis\n await page.waitForSelector('.table-list, .available-tables');\n \n // Conta quantas mesas est\u00e3o vis\u00edveis\n const tableCount = await page.$$eval('.table-item, .table-card', tables => tables.length);\n interactions.push({\n action: 'view_tables',\n count: tableCount,\n status: 'success'\n });\n \n // Simula clique na primeira mesa dispon\u00edvel\n const firstTable = await page.$('.table-item:first-child .join-btn, .table-card:first-child .join-table');\n if (firstTable) {\n await firstTable.click();\n await page.waitForSelector('.table-details, .game-room', { timeout: 5000 });\n \n interactions.push({\n action: 'join_table',\n status: 'success'\n });\n \n // Simula intera\u00e7\u00e3o no chat (se dispon\u00edvel)\n const chatInput = await page.$('.chat-input, #chat-message');\n if (chatInput) {\n await chatInput.type('Ol\u00e1 pessoal! Pronto para a aventura! \ud83c\udfb2');\n await page.click('.send-message, .chat-send');\n \n interactions.push({\n action: 'send_chat_message',\n status: 'success'\n });\n }\n \n // Simula rolagem de dados (se dispon\u00edvel)\n const diceRoll = await page.$('.roll-dice, .dice-roller');\n if (diceRoll) {\n await diceRoll.click();\n await page.waitForTimeout(2000); // Aguarda anima\u00e7\u00e3o\n \n interactions.push({\n action: 'roll_dice',\n status: 'success'\n });\n }\n }\n \n} catch (error) {\n interactions.push({\n action: 'player_interaction',\n status: 'failed',\n error: error.message\n });\n}\n\nreturn {\n player_interactions: interactions,\n timestamp: new Date().toISOString()\n};"
},
"id": "simulate-player-interactions",
"name": "\ud83c\udfae Simulate Player Interactions",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2000,
300
]
},
{
"parameters": {
"jsCode": "// Captura screenshots para valida\u00e7\u00e3o visual\nconst screenshots = [];\n\ntry {\n // Screenshot da p\u00e1gina principal\n const mainPage = await page.screenshot({ \n fullPage: true,\n type: 'png',\n encoding: 'base64'\n });\n \n screenshots.push({\n name: 'main_page',\n data: mainPage,\n timestamp: new Date().toISOString()\n });\n \n // Navega para diferentes se\u00e7\u00f5es e captura\n const sections = [\n { selector: '.inventory, #inventory', name: 'inventory' },\n { selector: '.characters, #characters', name: 'characters' },\n { selector: '.tables, #tables', name: 'tables' }\n ];\n \n for (const section of sections) {\n try {\n const element = await page.$(section.selector);\n if (element) {\n await element.click();\n await page.waitForTimeout(1000);\n \n const screenshot = await page.screenshot({\n type: 'png',\n encoding: 'base64'\n });\n \n screenshots.push({\n name: section.name,\n data: screenshot,\n timestamp: new Date().toISOString()\n });\n }\n } catch (sectionError) {\n screenshots.push({\n name: section.name,\n error: sectionError.message,\n timestamp: new Date().toISOString()\n });\n }\n }\n \n} catch (error) {\n screenshots.push({\n name: 'error_capture',\n error: error.message,\n timestamp: new Date().toISOString()\n });\n}\n\nreturn {\n visual_validation: screenshots,\n total_screenshots: screenshots.length\n};"
},
"id": "visual-validation",
"name": "\ud83d\udcf8 Visual Validation",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2220,
300
]
},
{
"parameters": {
"jsCode": "// Gera relat\u00f3rio completo da simula\u00e7\u00e3o de interface\nconst testData = $input.all();\n\nlet report = {\n test_session: new Date().toISOString(),\n frontend_url: 'http://localhost:3001',\n test_type: 'Human-Like Interface Automation',\n results: {\n registration: null,\n character_creation: null,\n table_creation: null,\n player_interactions: null,\n visual_validation: null\n },\n summary: {\n total_tests: 0,\n successful_tests: 0,\n failed_tests: 0,\n success_rate: 0\n }\n};\n\n// Processa dados de cada etapa\ntestData.forEach(item => {\n if (item.json) {\n const data = item.json;\n \n // Registra resultados de cria\u00e7\u00e3o de personagens\n if (Array.isArray(data) && data[0]?.character) {\n report.results.character_creation = data;\n report.summary.total_tests += data.length;\n report.summary.successful_tests += data.filter(c => c.status === 'created').length;\n }\n \n // Registra resultado de cria\u00e7\u00e3o de mesa\n if (data.table) {\n report.results.table_creation = data;\n report.summary.total_tests += 1;\n if (data.status === 'created') report.summary.successful_tests += 1;\n }\n \n // Registra intera\u00e7\u00f5es do jogador\n if (data.player_interactions) {\n report.results.player_interactions = data;\n const interactions = data.player_interactions;\n report.summary.total_tests += interactions.length;\n report.summary.successful_tests += interactions.filter(i => i.status === 'success').length;\n }\n \n // Registra valida\u00e7\u00e3o visual\n if (data.visual_validation) {\n report.results.visual_validation = data;\n const validations = data.visual_validation;\n report.summary.total_tests += validations.length;\n report.summary.successful_tests += validations.filter(v => !v.error).length;\n }\n }\n});\n\n// Calcula taxa de sucesso\nreport.summary.failed_tests = report.summary.total_tests - report.summary.successful_tests;\nreport.summary.success_rate = report.summary.total_tests > 0 ? \n (report.summary.successful_tests / report.summary.total_tests * 100).toFixed(1) : 0;\n\n// Adiciona conclus\u00f5es\nreport.conclusions = {\n interface_usability: report.summary.success_rate > 80 ? 'Excelente' : \n report.summary.success_rate > 60 ? 'Boa' : 'Precisa melhorar',\n user_experience: report.results.player_interactions?.player_interactions?.length > 0 ? \n 'Interativo' : 'Limitado',\n visual_quality: report.results.visual_validation?.total_screenshots > 0 ? \n 'Capturado' : 'N\u00e3o verificado',\n automation_status: 'Completo - Simula\u00e7\u00e3o de usu\u00e1rio real via interface'\n};\n\nreturn report;"
},
"id": "generate-ui-report",
"name": "\ud83d\udcca Generate UI Test Report",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2440,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "={{ $json.summary.success_rate }}",
"operation": "largerEqual",
"rightValue": 70
}
}
},
"id": "check-success-rate",
"name": "\u2705 Check Success Rate",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
2660,
300
]
},
{
"parameters": {
"message": "\ud83c\udf89 SUCESSO: Automa\u00e7\u00e3o de Interface Dungeon Keeper\n\n\ud83d\udcca Relat\u00f3rio: {{ $json.summary.success_rate }}% de sucesso\n\ud83c\udfad Personagens: {{ $json.results.character_creation?.length || 0 }} criados\n\ud83c\udfb2 Mesas: {{ $json.results.table_creation?.status === 'created' ? '1 criada' : '0 criadas' }}\n\ud83c\udfae Intera\u00e7\u00f5es: {{ $json.results.player_interactions?.player_interactions?.length || 0 }} realizadas\n\ud83d\udcf8 Capturas: {{ $json.results.visual_validation?.total_screenshots || 0 }} screenshots\n\n\u2728 Interface funcionando como esperado!",
"title": "\u2705 Teste de Interface - SUCESSO"
},
"id": "success-notification",
"name": "\ud83c\udf89 Success Notification",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
2880,
200
]
},
{
"parameters": {
"message": "\u26a0\ufe0f ATEN\u00c7\u00c3O: Problemas na Interface Dungeon Keeper\n\n\ud83d\udcca Relat\u00f3rio: {{ $json.summary.success_rate }}% de sucesso\n\u274c Falhas: {{ $json.summary.failed_tests }} de {{ $json.summary.total_tests }}\n\n\ud83d\udd0d Verificar:\n- Elementos da interface\n- Responsividade\n- Funcionalidades b\u00e1sicas\n- Navega\u00e7\u00e3o entre p\u00e1ginas\n\n\ud83d\udee0\ufe0f A\u00e7\u00e3o necess\u00e1ria para melhorar UX!",
"title": "\u26a0\ufe0f Teste de Interface - PROBLEMAS"
},
"id": "failure-notification",
"name": "\u26a0\ufe0f Failure Notification",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
2880,
400
]
}
],
"connections": {
"schedule-trigger": {
"main": [
[
{
"node": "open-frontend",
"type": "main",
"index": 0
}
]
]
},
"open-frontend": {
"main": [
[
{
"node": "fill-email",
"type": "main",
"index": 0
},
{
"node": "fill-password",
"type": "main",
"index": 0
},
{
"node": "fill-username",
"type": "main",
"index": 0
}
]
]
},
"fill-email": {
"main": [
[
{
"node": "click-register",
"type": "main",
"index": 0
}
]
]
},
"fill-password": {
"main": [
[
{
"node": "click-register",
"type": "main",
"index": 0
}
]
]
},
"fill-username": {
"main": [
[
{
"node": "click-register",
"type": "main",
"index": 0
}
]
]
},
"click-register": {
"main": [
[
{
"node": "navigate-character-creation",
"type": "main",
"index": 0
}
]
]
},
"navigate-character-creation": {
"main": [
[
{
"node": "create-characters-ui",
"type": "main",
"index": 0
}
]
]
},
"create-characters-ui": {
"main": [
[
{
"node": "navigate-tables",
"type": "main",
"index": 0
}
]
]
},
"navigate-tables": {
"main": [
[
{
"node": "create-table-ui",
"type": "main",
"index": 0
}
]
]
},
"create-table-ui": {
"main": [
[
{
"node": "simulate-player-interactions",
"type": "main",
"index": 0
}
]
]
},
"simulate-player-interactions": {
"main": [
[
{
"node": "visual-validation",
"type": "main",
"index": 0
}
]
]
},
"visual-validation": {
"main": [
[
{
"node": "generate-ui-report",
"type": "main",
"index": 0
}
]
]
},
"generate-ui-report": {
"main": [
[
{
"node": "check-success-rate",
"type": "main",
"index": 0
}
]
]
},
"check-success-rate": {
"main": [
[
{
"node": "success-notification",
"type": "main",
"index": 0
}
],
[
{
"node": "failure-notification",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "1",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "human-like-interface-testing",
"tags": [
{
"createdAt": "2025-01-31T03:01:00.000Z",
"updatedAt": "2025-01-31T03:01:00.000Z",
"id": "ui-testing",
"name": "UI Testing"
},
{
"createdAt": "2025-01-31T03:01:00.000Z",
"updatedAt": "2025-01-31T03:01:00.000Z",
"id": "automation",
"name": "Automation"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Human-Like Interface Testing - Dungeon Keeper. Uses puppeteer. Scheduled trigger; 16 nodes.
Source: https://github.com/bugijo/DK/blob/e3a808969cc5a36e1f734cdcb681d90d85dd8027/n8n-automation/workflows/human-like-interface-testing.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
> Watch the full Youtube Video Tutorial [](https://youtu.be/Y-wUr2-UYZk)
Very straightforward workflow. It checks the Epic Games website if the HTML container with free games has changed. If it did then it will send a notification to Discord with a list of embeds containin
This workflow automatically scrapes business leads from Google Maps on a daily schedule and ensures only high-quality, unique leads are processed. New businesses are cleaned, validated, and deduplicat
Women creators, homemakers-turned-entrepreneurs, and feminine lifestyle brands who want a graceful, low-lift way to keep an eye on competitor content and spark weekly ideas.
This workflow automatically searches YouTube Data API for videos related to specific keywords, extracts channel data, filters channels based on performance metrics, and saves the results into Google S