SaaS/test/app.test.js
Claude Code d1b5b72c46 🚀 Transform into full SaaS Automation Platform
Major Update: From simple click counter to comprehensive automation platform

## New Features:
 Full user authentication (register/login/logout)
 SQLite database with user management
 API credentials management system
 Workflow templates library (4 ready-to-use templates)
 User workflow management
 Comprehensive dashboard interface
 Detailed n8n integration instructions
 Security features (bcrypt, sessions, helmet)
 Automated testing suite (14 passing tests)

## Technical Stack:
- Backend: Node.js + Express + SQLite
- Frontend: Vanilla JS + Modern CSS
- Security: bcrypt, express-session, helmet
- Database: SQLite with proper schemas and indexes
- Testing: Mocha + Chai + Supertest

## Templates Included:
1. 📱 Telegram Bot Notifications
2. 📧 Email to Slack Integration
3. 💾 Google Drive Backup Automation
4. 📊 Lead Scoring Automation

## Access Points:
- Legacy app: http://localhost:3000/
- SaaS Platform: http://localhost:3000/dashboard
- API endpoints: /api/*

## Demo Credentials:
- Email: demo@example.com
- Password: demo123

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 11:05:29 +01:00

211 lines
No EOL
6.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const request = require('supertest');
const { expect } = require('chai');
// Для локального тестирования
// const app = require('../server');
// Для удаленного тестирования
const BASE_URL = process.env.TEST_URL || 'http://128.140.8.206:3000';
describe('Click Counter Application', () => {
describe('Health Check', () => {
it('should return health status', (done) => {
request(BASE_URL)
.get('/health')
.expect(200)
.expect('Content-Type', /json/)
.end((err, res) => {
if (err) return done(err);
expect(res.body).to.have.property('status', 'ok');
done();
});
});
});
describe('Static Files', () => {
it('should serve main HTML page', (done) => {
request(BASE_URL)
.get('/')
.expect(200)
.expect('Content-Type', /text\/html/)
.end((err, res) => {
if (err) return done(err);
expect(res.text).to.include('<!doctype html>');
expect(res.text).to.include('Счётчик кликов');
expect(res.text).to.include('<script src="/main.js" defer></script>');
expect(res.text).to.include('<link rel="stylesheet" href="/style.css">');
done();
});
});
it('should serve JavaScript file', (done) => {
request(BASE_URL)
.get('/main.js')
.expect(200)
.expect('Content-Type', /application\/javascript/)
.end((err, res) => {
if (err) return done(err);
expect(res.text).to.include('localStorage');
expect(res.text).to.include('clickCounterValue');
expect(res.text).to.include('addEventListener');
done();
});
});
it('should serve CSS file', (done) => {
request(BASE_URL)
.get('/style.css')
.expect(200)
.expect('Content-Type', /text\/css/)
.end((err, res) => {
if (err) return done(err);
expect(res.text).to.include(':root');
expect(res.text).to.include('--bg');
expect(res.text).to.include('button');
done();
});
});
});
describe('Application Structure', () => {
it('should contain required DOM elements', (done) => {
request(BASE_URL)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
const html = res.text;
// Проверяем наличие необходимых элементов
expect(html).to.include('id="value"');
expect(html).to.include('id="inc"');
expect(html).to.include('id="reset"');
expect(html).to.include('class="counter"');
expect(html).to.include('class="container"');
done();
});
});
it('should have proper meta tags', (done) => {
request(BASE_URL)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
const html = res.text;
expect(html).to.include('<meta charset="utf-8">');
expect(html).to.include('<meta name="viewport"');
expect(html).to.include('<title>Счётчик кликов</title>');
done();
});
});
});
describe('Error Handling', () => {
it('should return 404 for non-existent routes', (done) => {
request(BASE_URL)
.get('/nonexistent')
.expect(404)
.end(done);
});
it('should handle POST requests gracefully', (done) => {
request(BASE_URL)
.post('/')
.expect(404)
.end(done);
});
});
describe('Performance', () => {
it('should respond quickly (< 1000ms)', (done) => {
const start = Date.now();
request(BASE_URL)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
const responseTime = Date.now() - start;
expect(responseTime).to.be.below(1000);
done();
});
});
it('should have proper caching headers', (done) => {
request(BASE_URL)
.get('/style.css')
.expect(200)
.end((err, res) => {
if (err) return done(err);
expect(res.headers).to.have.property('cache-control');
expect(res.headers).to.have.property('etag');
done();
});
});
});
describe('Security', () => {
it('should have X-Powered-By header', (done) => {
request(BASE_URL)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
expect(res.headers).to.have.property('x-powered-by', 'Express');
done();
});
});
it('should handle various HTTP methods', (done) => {
request(BASE_URL)
.options('/')
.end((err, res) => {
// OPTIONS должен либо работать, либо возвращать 404/405
expect([200, 404, 405]).to.include(res.status);
done();
});
});
});
describe('Content Validation', () => {
it('should have valid HTML structure', (done) => {
request(BASE_URL)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
const html = res.text;
// Проверяем базовую HTML структуру
expect(html).to.match(/<!doctype html>/i);
expect(html).to.include('<html');
expect(html).to.include('<head>');
expect(html).to.include('<body>');
expect(html).to.include('</html>');
// Проверяем отсутствие разорванных тегов
expect(html).to.not.include('<script></script>');
expect(html).to.not.include('undefined');
done();
});
});
it('should contain Russian language content', (done) => {
request(BASE_URL)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
const html = res.text;
expect(html).to.include('lang="ru"');
expect(html).to.include('Счётчик кликов');
expect(html).to.include('Сброс');
done();
});
});
});
});