Compare commits
8 Commits
b79153d477
...
d1eed36b6e
Author | SHA1 | Date |
---|---|---|
|
d1eed36b6e | 1 year ago |
|
a815f1c168 | 1 year ago |
|
896664af07 | 1 year ago |
|
3316d1f98a | 1 year ago |
|
de51a93fde | 1 year ago |
|
5760e3b4dd | 1 year ago |
|
4826c679e8 | 1 year ago |
|
4914bf1764 | 1 year ago |
@ -0,0 +1,3 @@ |
||||
--require spec_helper |
||||
--format progress |
||||
--format html --out tmp/rspec.html |
@ -1,4 +1,4 @@ |
||||
web: bundle exec guard -i |
||||
webpack: bundle exec webpack-dev-server |
||||
webpack: bundle exec bin/webpack-dev-server |
||||
sidekiq: bundle exec sidekiq -q default |
||||
sidekiq_1_0: BUNDLE_GEMFILE=Gemfile-2.3 bin/sidekiq 1.0 -q tls_1_0 |
||||
|
@ -0,0 +1,23 @@ |
||||
class StatisticsController < ApplicationController |
||||
TODAY = Date.today |
||||
|
||||
def show |
||||
service = params.fetch :id |
||||
respond_to do |format| |
||||
format.json do |
||||
json = Stat.where(name: "grades_for_#{service}").order(date: :desc).first.data |
||||
render json: json, status: :ok |
||||
end |
||||
end |
||||
end |
||||
|
||||
def ciphers |
||||
service = params.fetch :id |
||||
render json: Stat.where(name: "ciphers_for_#{service}").order(date: :desc).first.data |
||||
end |
||||
|
||||
def tls |
||||
service = params.fetch :id |
||||
render json: Stat.where(name: "tls_for_#{service}").order(date: :desc).first.data |
||||
end |
||||
end |
@ -0,0 +1,2 @@ |
||||
module StatisticsHelper |
||||
end |
@ -0,0 +1,5 @@ |
||||
$dark: #3f4853; |
||||
|
||||
$link-color: #135262; |
||||
|
||||
$nav-pills-link-active-bg: #535d6c; |
@ -0,0 +1,44 @@ |
||||
document.addEventListener("DOMContentLoaded", () => { |
||||
if (document.getElementById("pills-tab")) { |
||||
let background = [ |
||||
'#d9534f', // bad
|
||||
'#5cb85c' // good
|
||||
] |
||||
|
||||
for (const service of ["https", "smtp", "tls", "xmpp"]) { |
||||
const name = service.replace(/^\w/, c => c.toUpperCase()) |
||||
const canvas = document.getElementById(`ciphers${name}Chart`).getContext('2d') |
||||
const chart = new Chart(canvas, { |
||||
type: 'doughnut', options: { |
||||
interaction: { |
||||
intersect: false, mode: 'dataset', |
||||
}, |
||||
animations: { |
||||
tension: { |
||||
duration: 100, |
||||
easing: 'linear', |
||||
from: 1, |
||||
to: 0, |
||||
loop: false |
||||
} |
||||
}, |
||||
} |
||||
}) |
||||
|
||||
fetch(`/statistics/${service}/ciphers.json`).then((response) => { |
||||
if (response.status === 200) { |
||||
response.json().then((data) => { |
||||
console.info(data) |
||||
const labels = Object.keys(data) |
||||
const dataset = Object.values(data) |
||||
chart.data.labels = labels |
||||
chart.data.datasets = [{ |
||||
label: 'Number of request', data: dataset, backgroundColor: background |
||||
}] |
||||
chart.update() |
||||
}) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
}) |
@ -0,0 +1,40 @@ |
||||
document.addEventListener("DOMContentLoaded", () => { |
||||
let gradesChart = document.getElementById('gradesChart').getContext('2d') |
||||
|
||||
let background = [ |
||||
'rgba(255, 99, 132, 1)', |
||||
'rgba(54, 162, 235, 1)', |
||||
'rgba(255, 206, 86, 1)', |
||||
'rgba(75, 192, 192, 1)', |
||||
'rgba(153, 102, 255, 1)', |
||||
'rgba(255, 159, 64, 1)' |
||||
] |
||||
|
||||
let createGradesChart = new Chart(gradesChart, { |
||||
type: 'bar' |
||||
}) |
||||
|
||||
let generateGraphs = function () { |
||||
fetch(window.location.href, { |
||||
method: "GET", |
||||
headers: { |
||||
"Accept": "application/json", |
||||
"Content-Type": "application/json", |
||||
}, |
||||
}).then((response) => { |
||||
response.json().then((data) => { |
||||
if (response.status === 200) { |
||||
createGradesChart.data.labels = data["labels"] |
||||
createGradesChart.data.datasets = [{ |
||||
label: 'Number', |
||||
data: data["dataset"], |
||||
backgroundColor: background |
||||
}] |
||||
createGradesChart.update() |
||||
} |
||||
}) |
||||
}); |
||||
} |
||||
|
||||
generateGraphs() |
||||
}); |
@ -0,0 +1,73 @@ |
||||
document.addEventListener("DOMContentLoaded", () => { |
||||
let background = [ |
||||
'#5cb85c', // A+
|
||||
'#5cb85c', // A
|
||||
'#8db457', // B+
|
||||
'#8db457', // B
|
||||
'#beb052', // C+
|
||||
'#beb052', // C
|
||||
'#6c757d', // D
|
||||
'#f0ad4e', // E
|
||||
'#e4804e', // F
|
||||
'#d9534f' // G
|
||||
] |
||||
|
||||
for (const service of ["https", "smtp", "tls", "xmpp"]) { |
||||
const name = service.replace(/^\w/, c => c.toUpperCase()) |
||||
console.info(`grades${name}Chart`) |
||||
const canvas = document.getElementById(`grades${name}Chart`).getContext('2d') |
||||
// const chart = new Chart(canvas, {
|
||||
// type: 'pie',
|
||||
// options: {
|
||||
// interaction: {
|
||||
// intersect: false,
|
||||
// mode: 'dataset',
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
const chart = new Chart(canvas, { |
||||
type: 'bar', |
||||
options: { |
||||
interaction: { |
||||
intersect: false, |
||||
mode: 'dataset', |
||||
}, |
||||
plugins: { |
||||
datalabels: { |
||||
anchor: 'end', |
||||
align: 'top', |
||||
formatter: ((value, context) => { |
||||
const index = context.dataIndex |
||||
const keys = Object.keys(context.dataset.data) |
||||
value = context.dataset.data[keys[index]] |
||||
return value |
||||
}), |
||||
color: "black", |
||||
font: { |
||||
weight: "bold", |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
fetch(`/statistics/${service}.json`).then((response) => { |
||||
if (response.status === 200) { |
||||
response.json().then((data) => { |
||||
console.info(data) |
||||
const labels = ["A+", "A", "B+", "B", "C+", "C", "D", "E", "F", "G"] |
||||
const dataset = JSON.parse(JSON.stringify(data, labels, 0)) |
||||
chart.data.labels = labels |
||||
chart.data.datasets = [{ |
||||
label: 'Number of request', |
||||
data: dataset, |
||||
backgroundColor: background |
||||
}] |
||||
chart.update() |
||||
}) |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
) |
||||
; |
@ -0,0 +1,46 @@ |
||||
document.addEventListener("DOMContentLoaded", () => { |
||||
if (document.getElementById("pills-tab")) { |
||||
let background = [ |
||||
'#d9534f', // ssl
|
||||
'#beb052', // tls
|
||||
'#beb052', // tls
|
||||
'#5cb85c' // tls1_2_only
|
||||
] |
||||
|
||||
for (const service of ["https", "smtp", "tls", "xmpp"]) { |
||||
const name = service.replace(/^\w/, c => c.toUpperCase()) |
||||
const canvas = document.getElementById(`tls${name}Chart`).getContext('2d') |
||||
const chart = new Chart(canvas, { |
||||
type: 'doughnut', options: { |
||||
interaction: { |
||||
intersect: false, mode: 'dataset', |
||||
}, |
||||
animations: { |
||||
tension: { |
||||
duration: 100, |
||||
easing: 'linear', |
||||
from: 1, |
||||
to: 0, |
||||
loop: false |
||||
} |
||||
}, |
||||
} |
||||
}) |
||||
|
||||
fetch(`/statistics/${service}/tls.json`).then((response) => { |
||||
if (response.status === 200) { |
||||
response.json().then((data) => { |
||||
console.info(data) |
||||
const labels = Object.keys(data) |
||||
const dataset = Object.values(data) |
||||
chart.data.labels = labels |
||||
chart.data.datasets = [{ |
||||
label: 'Number of request', data: dataset, backgroundColor: background |
||||
}] |
||||
chart.update() |
||||
}) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
}) |
@ -1 +1,10 @@ |
||||
import 'css/application' |
||||
|
||||
import 'bootstrap' |
||||
import Chart from 'chart.js/auto' |
||||
import ChartDataLabels from 'chartjs-plugin-datalabels' |
||||
global.Chart = Chart |
||||
Chart.register(ChartDataLabels) |
||||
|
||||
import 'js/stats/ciphers' |
||||
import 'js/stats/tls' |
@ -1,36 +1,36 @@ |
||||
class Analysis < ApplicationRecord |
||||
enum service: %i[https smtp xmpp tls ssh].collect { |e| [e, e.to_s] }.to_h |
||||
validates :service, presence: true |
||||
validates :host, presence: true |
||||
enum service: %i[https smtp xmpp tls ssh].collect { |e| [e, e.to_s] }.to_h |
||||
validates :service, presence: true |
||||
validates :host, presence: true |
||||
|
||||
def self.[](service, host, args) |
||||
key = self.key service, host, args |
||||
self.find_by key |
||||
end |
||||
def self.[](service, host, args) |
||||
key = self.key service, host, args |
||||
self.find_by key |
||||
end |
||||
|
||||
def self.pending!(service, host, args) |
||||
key = self.key service, host, args |
||||
analysis = self.find_or_create_by! key |
||||
analysis.pending! |
||||
end |
||||
def self.pending!(service, host, args) |
||||
key = self.key service, host, args |
||||
analysis = self.find_or_create_by! key |
||||
analysis.pending! |
||||
end |
||||
|
||||
def pending! |
||||
self.update! pending: true |
||||
self |
||||
end |
||||
def pending! |
||||
self.update! pending: true |
||||
self |
||||
end |
||||
|
||||
def self.post!(service, host, args, result) |
||||
analysis = self[service, host, args] |
||||
analysis.post! result |
||||
end |
||||
def self.post!(service, host, args, result) |
||||
analysis = self[service, host, args] |
||||
analysis.post! result |
||||
end |
||||
|
||||
def post!(result) |
||||
self.update! pending: false, result: result |
||||
end |
||||
def post!(result) |
||||
self.update! pending: false, result: result |
||||
end |
||||
|
||||
private |
||||
private |
||||
|
||||
def self.key(service, host, args) |
||||
{ service: service, host: host, args: args } |
||||
end |
||||
def self.key(service, host, args) |
||||
{ service: service, host: host, args: args } |
||||
end |
||||
end |
||||
|
@ -0,0 +1,10 @@ |
||||
class Stat < ApplicationRecord |
||||
def self.create!(name, data, date = Date.today) |
||||
self.delete_by name: name, date: date |
||||
super name: name, date: date, data: data |
||||
end |
||||
|
||||
def self.[](name) |
||||
self.where(name: name).order(date: :desc).limit(1).first |
||||
end |
||||
end |
@ -0,0 +1,117 @@ |
||||
<% colors = { |
||||
"A+" => '#5cb85c', |
||||
"good" => '#5cb85c', |
||||
"A" => '#5cb85c', |
||||
"B+" => '#8db457', |
||||
"B" => '#8db457', |
||||
"C+" => '#beb052', |
||||
"C" => '#beb052', |
||||
"D" => '#6c757d', |
||||
"E" => '#f0ad4e', |
||||
"F" => '#e4804e', |
||||
"G" => '#d9534f', |
||||
"bad" => '#d9534f' } %> |
||||
|
||||
<ul class="nav nav-pills nav-fill" id="pills-tab" role="tab-list"> |
||||
<% %i[https smtp tls xmpp].each do |service| %> |
||||
<li class="nav-item" role="presentation"> |
||||
<button class="nav-link<%= " active btn-dark" if service.to_s == "https" %>" |
||||
id="nav-<%= service %>-pill" data-bs-toggle="pill" |
||||
data-bs-target="#nav-<%= service %>" type="button" role="pill" aria-controls="nav-<%= service %>" aria-selected="true"> |
||||
<%= service.to_s.upcase %> |
||||
</button> |
||||
</li> |
||||
<% end %> |
||||
</ul> |
||||
|
||||
<div class="tab-content p-2" id="nav-pillsContent"> |
||||
<% %i[https smtp tls xmpp].each do |service| %> |
||||
<div class="tab-pane fade show <%= "active" if service.to_s == "https" %>" id="nav-<%= service %>" role="tabpanel" aria-labelledby="nav-<%= service %>-pill"> |
||||
<h2>Grades for service <%= service.to_s.upcase %></h2> |
||||
|
||||
|
||||
<% grades = Stat.where(name: "grades_for_#{service}").order(date: :desc).first |
||||
total = grades.data.collect { _2 }.sum %> |
||||
|
||||
<p>Over <%= total %> URL tested with a grade.</p> |
||||
|
||||
<div class="cumulative-datas"> |
||||
<% left = 0 |
||||
percent_total = 100 |
||||
grades.data.sort_by(&:first).each do |grade, number| |
||||
%> |
||||
<% unless %w(T V).include?(grade) |
||||
percent = (number.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] |
||||
if percent > 1 %> |
||||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: <%= color %>;"> |
||||
<%= "#{grade}: #{percent.round}% (#{number})" %> |
||||
</div> |
||||
<% left += percent.round |
||||
end |
||||
end |
||||
end |
||||
percent = percent_total - left %> |
||||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
||||
<%= "other: #{percent.round}%" %> |
||||
</div> |
||||
</div> |
||||
|
||||
<h2>Ciphers for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% ciphers = Stat.where(name: "ciphers_for_#{service}").order(date: :desc).first |
||||
total = ciphers.data.collect { _2 }.sum |
||||
%> |
||||
<p>Over <%= total %> URL tested with a cipher.</p> |
||||
|
||||
<div class="cumulative-datas"> |
||||
<% left = 0 |
||||
percent_total = 100 |
||||
ciphers.data.sort_by(&:first).each do |grade, number| |
||||
%> |
||||
<% |
||||
percent = (number.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] %> |
||||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: <%= color %>;"> |
||||
<%= "#{grade.capitalize}: #{percent.round}% (#{number})" %> |
||||
</div> |
||||
<% left += percent.round |
||||
end |
||||
percent = percent_total - left |
||||
if percent > 0 %> |
||||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
||||
<%= "Other: #{percent.round}%" %> |
||||
</div> |
||||
<% end %> |
||||
</div> |
||||
|
||||
<h2>TLS for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% tls = Stat.where(name: "tls_for_#{service}").order(date: :desc).first |
||||
total = tls.data.collect { _2 }.sum |
||||
%> |
||||
<p>Over <%= total %> URL tested with TLS.</p> |
||||
|
||||
<div class="cumulative-datas"> |
||||
<% left = 0 |
||||
percent_total = 100 |
||||
tls.data.sort_by(&:first).each do |grade, number| |
||||
%> |
||||
<% |
||||
percent = (number.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] %> |
||||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
||||
<%= "#{grade.capitalize}: #{percent.round}% (#{number})" %> |
||||
</div> |
||||
<% left += percent.round |
||||
end |
||||
percent = percent_total - left |
||||
if percent > 0 %> |
||||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
||||
<%= "Other: #{percent.round}%" %> |
||||
</div> |
||||
<% end %> |
||||
</div> |
||||
</div> |
||||
<% end %> |
||||
</div> |
@ -0,0 +1,29 @@ |
||||
#!/usr/bin/env ruby |
||||
# frozen_string_literal: true |
||||
|
||||
# |
||||
# This file was generated by Bundler. |
||||
# |
||||
# The application 'rspec' is installed as part of a gem, and |
||||
# this file is here to facilitate running it. |
||||
# |
||||
|
||||
require "pathname" |
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", |
||||
Pathname.new(__FILE__).realpath) |
||||
|
||||
bundle_binstub = File.expand_path("../bundle", __FILE__) |
||||
|
||||
if File.file?(bundle_binstub) |
||||
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ |
||||
load(bundle_binstub) |
||||
else |
||||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. |
||||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") |
||||
end |
||||
end |
||||
|
||||
require "rubygems" |
||||
require "bundler/setup" |
||||
|
||||
load Gem.bin_path("rspec-core", "rspec") |
@ -0,0 +1,96 @@ |
||||
#!./bin/rails runner |
||||
|
||||
# Profit from open class to add stats methods only on this script |
||||
class Analysis |
||||
def grade |
||||
return if self.pending |
||||
grades = self.result.collect { _1['grade'] }.compact |
||||
CryptCheck::Grade.worst grades |
||||
end |
||||
|
||||
def tls |
||||
return if self.pending |
||||
return unless (result = self.result) |
||||
protocols = result.collect { |r| r.dig('handshakes', 'protocols') |
||||
&.collect { |p| p['protocol'].to_sym } } |
||||
.compact.flatten.uniq |
||||
|
||||
return :ssl if %i[SSLv2 SSLv3].any? { protocols.include? _1 } |
||||
return :tls unless protocols.include? :TLSv1_2 |
||||
return :tls1_2 unless protocols == %i[TLSv1_2] |
||||
:tls1_2_only |
||||
end |
||||
|
||||
def ciphers |
||||
return if self.pending |
||||
return unless (result = self.result) |
||||
status = result.collect do |r| |
||||
r.dig('handshakes', 'ciphers')&.collect do |c| |
||||
s = CryptCheck::Tls::Cipher |
||||
.new(nil, c.fetch('name')).status |
||||
CryptCheck::State.good_or_bad s |
||||
end |
||||
end.compact.flatten.uniq |
||||
|
||||
return :bad unless status.include? :bad |
||||
:good |
||||
end |
||||
|
||||
def pfs |
||||
return if self.pending |
||||
return unless (result = self.result) |
||||
ciphers = result.collect do |r| |
||||
r.dig('handshakes', 'ciphers')&.collect do |c| |
||||
CryptCheck::Tls::Cipher |
||||
.new(nil, c.fetch('name')) |
||||
.pfs? |
||||
end |
||||
end.compact.flatten.uniq |
||||
|
||||
return :no_pfs unless ciphers.include? true |
||||
return :pfs unless ciphers == [true] |
||||
:pfs_only |
||||
end |
||||
end |
||||
|
||||
services = Analysis.group(:service).count |
||||
Stat.create! :request_per_service, services |
||||
|
||||
%i[https smtp tls xmpp].each do |service| |
||||
services = Analysis.where service: service, pending: false |
||||
|
||||
grades = Hash.new 0 |
||||
tls = %i[tls1_2_only tls1_2 tls ssl].to_h { [_1, 0] } |
||||
ciphers = %i[good bad].to_h { [_1, 0] } |
||||
pfs = %i[pfs_only pfs no_pfs].to_h { [_1, 0] } |
||||
|
||||
services.each do |service| |
||||
if (g = service.grade) |
||||
grades[g] += 1 |
||||
end |
||||
|
||||
if (t = service.tls) |
||||
tls[t] += 1 |
||||
end |
||||
|
||||
if (c = service.ciphers) |
||||
ciphers[c] += 1 |
||||
end |
||||
|
||||
if (p = service.pfs) |
||||
pfs[p] += 1 |
||||
end |
||||
end |
||||
|
||||
ap "grades_for_#{service}" => grades |
||||
Stat.create! "grades_for_#{service}", grades |
||||
|
||||
ap "tls_for_#{service}" => tls |
||||
Stat.create! "tls_for_#{service}", tls |
||||
|
||||
ap "ciphers_for_#{service}" => ciphers |
||||
Stat.create! "ciphers_for_#{service}", ciphers |
||||
|
||||
ap "pfs_for_#{service}" => pfs |
||||
Stat.create! "pfs_for_#{service}", pfs |
||||
end |
@ -0,0 +1,11 @@ |
||||
class CreateStats < ActiveRecord::Migration[7.0] |
||||
def change |
||||
create_table :stats, id: :uuid do |t| |
||||
t.string :name |
||||
t.date :date |
||||
t.jsonb :data |
||||
end |
||||
|
||||
add_index :stats, %i[name] |
||||
end |
||||
end |
@ -0,0 +1,65 @@ |
||||
require 'rails_helper' |
||||
|
||||
describe Stat do |
||||
before do |
||||
Stat.delete_all |
||||
end |
||||
|
||||
describe '#create!' do |
||||
it 'must create stats if not existing' do |
||||
name = 'foo' |
||||
today = Date.today |
||||
data = { 'bar' => 'baz' } |
||||
expect { Stat.create! name, data } |
||||
.to change { Stat.count }.from(0).to(1) |
||||
stat = Stat.first |
||||
expect(stat.name).to eq name |
||||
expect(stat.date).to eq today |
||||
expect(stat.data).to eq data |
||||
end |
||||
|
||||
it 'must delete existing date if exist' do |
||||
name = 'foo' |
||||
today = Date.today |
||||
data = { 'bar' => 'baz' } |
||||
expect { Stat.create! name, data } |
||||
.to change { Stat.count }.from(0).to(1) |
||||
|
||||
data = { 'bar' => 'qux' } |
||||
expect { Stat.create! name, data } |
||||
.to_not change { Stat.count } |
||||
|
||||
stat = Stat.first |
||||
expect(stat.name).to eq name |
||||
expect(stat.date).to eq today |
||||
expect(stat.data).to eq data |
||||
end |
||||
end |
||||
|
||||
describe '#[]' do |
||||
it 'must retrieve the youngest data' do |
||||
name = 'foo' |
||||
|
||||
stat = Stat[name] |
||||
expect(stat).to be_nil |
||||
|
||||
data = { 'bar' => 'baz' } |
||||
date = Date.new 1970, 1, 1 |
||||
Stat.create! name, data, date |
||||
|
||||
stat = Stat[name] |
||||
expect(stat).to_not be_nil |
||||
expect(stat.date).to eq date |
||||
expect(stat.data).to eq data |
||||
|
||||
data = { 'bar' => 'qux' } |
||||
date = Date.new 1970, 1, 2 |
||||
Stat.create! name, data, date |
||||
|
||||
stat = Stat[name] |
||||
expect(stat).to_not be_nil |
||||
expect(stat.date).to eq date |
||||
expect(stat.data).to eq data |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,64 @@ |
||||
# This file is copied to spec/ when you run 'rails generate rspec:install' |
||||
require 'spec_helper' |
||||
ENV['RAILS_ENV'] ||= 'test' |
||||
require_relative '../config/environment' |
||||
# Prevent database truncation if the environment is production |
||||
abort("The Rails environment is running in production mode!") if Rails.env.production? |
||||
require 'rspec/rails' |
||||
# Add additional requires below this line. Rails is not loaded until this point! |
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc, in |
||||
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are |
||||
# run as spec files by default. This means that files in spec/support that end |
||||
# in _spec.rb will both be required and run as specs, causing the specs to be |
||||
# run twice. It is recommended that you do not name files matching this glob to |
||||
# end with _spec.rb. You can configure this pattern with the --pattern |
||||
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. |
||||
# |
||||
# The following line is provided for convenience purposes. It has the downside |
||||
# of increasing the boot-up time by auto-requiring all files in the support |
||||
# directory. Alternatively, in the individual `*_spec.rb` files, manually |
||||
# require only the support files necessary. |
||||
# |
||||
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } |
||||
|
||||
# Checks for pending migrations and applies them before tests are run. |
||||
# If you are not using ActiveRecord, you can remove these lines. |
||||
begin |
||||
ActiveRecord::Migration.maintain_test_schema! |
||||
rescue ActiveRecord::PendingMigrationError => e |
||||
puts e.to_s.strip |
||||
exit 1 |
||||
end |
||||
RSpec.configure do |config| |
||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures |
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures" |
||||
|
||||
# If you're not using ActiveRecord, or you'd prefer not to run each of your |
||||
# examples within a transaction, remove the following line or assign false |
||||
# instead of true. |
||||
config.use_transactional_fixtures = true |
||||
|
||||
# You can uncomment this line to turn off ActiveRecord support entirely. |
||||
# config.use_active_record = false |
||||
|
||||
# RSpec Rails can automatically mix in different behaviours to your tests |
||||
# based on their file location, for example enabling you to call `get` and |
||||
# `post` in specs under `spec/controllers`. |
||||
# |
||||
# You can disable this behaviour by removing the line below, and instead |
||||
# explicitly tag your specs with their type, e.g.: |
||||
# |
||||
# RSpec.describe UsersController, type: :controller do |
||||
# # ... |
||||
# end |
||||
# |
||||
# The different available types are documented in the features, such as in |
||||
# https://relishapp.com/rspec/rspec-rails/docs |
||||
config.infer_spec_type_from_file_location! |
||||
|
||||
# Filter lines from Rails gems in backtraces. |
||||
config.filter_rails_from_backtrace! |
||||
# arbitrary gems may also be filtered via: |
||||
# config.filter_gems_from_backtrace("gem name") |
||||
end |
@ -0,0 +1,94 @@ |
||||
# This file was generated by the `rails generate rspec:install` command. Conventionally, all |
||||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. |
||||
# The generated `.rspec` file contains `--require spec_helper` which will cause |
||||
# this file to always be loaded, without a need to explicitly require it in any |
||||
# files. |
||||
# |
||||
# Given that it is always loaded, you are encouraged to keep this file as |
||||
# light-weight as possible. Requiring heavyweight dependencies from this file |
||||
# will add to the boot time of your test suite on EVERY test run, even for an |
||||
# individual file that may not need all of that loaded. Instead, consider making |
||||
# a separate helper file that requires the additional dependencies and performs |
||||
# the additional setup, and require it from the spec files that actually need |
||||
# it. |
||||
# |
||||
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration |
||||
RSpec.configure do |config| |
||||
# rspec-expectations config goes here. You can use an alternate |
||||
# assertion/expectation library such as wrong or the stdlib/minitest |
||||
# assertions if you prefer. |
||||
config.expect_with :rspec do |expectations| |
||||
# This option will default to `true` in RSpec 4. It makes the `description` |
||||
# and `failure_message` of custom matchers include text for helper methods |
||||
# defined using `chain`, e.g.: |
||||
# be_bigger_than(2).and_smaller_than(4).description |
||||
# # => "be bigger than 2 and smaller than 4" |
||||
# ...rather than: |
||||
# # => "be bigger than 2" |
||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true |
||||
end |
||||
|
||||
# rspec-mocks config goes here. You can use an alternate test double |
||||
# library (such as bogus or mocha) by changing the `mock_with` option here. |
||||
config.mock_with :rspec do |mocks| |
||||
# Prevents you from mocking or stubbing a method that does not exist on |
||||
# a real object. This is generally recommended, and will default to |
||||
# `true` in RSpec 4. |
||||
mocks.verify_partial_doubles = true |
||||
end |
||||
|
||||
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will |
||||
# have no way to turn it off -- the option exists only for backwards |
||||
# compatibility in RSpec 3). It causes shared context metadata to be |
||||
# inherited by the metadata hash of host groups and examples, rather than |
||||
# triggering implicit auto-inclusion in groups with matching metadata. |
||||
config.shared_context_metadata_behavior = :apply_to_host_groups |
||||
|
||||
# The settings below are suggested to provide a good initial experience |
||||
# with RSpec, but feel free to customize to your heart's content. |
||||
=begin |
||||
# This allows you to limit a spec run to individual examples or groups |
||||
# you care about by tagging them with `:focus` metadata. When nothing |
||||
# is tagged with `:focus`, all examples get run. RSpec also provides |
||||
# aliases for `it`, `describe`, and `context` that include `:focus` |
||||
# metadata: `fit`, `fdescribe` and `fcontext`, respectively. |
||||
config.filter_run_when_matching :focus |
||||
|
||||
# Allows RSpec to persist some state between runs in order to support |
||||
# the `--only-failures` and `--next-failure` CLI options. We recommend |
||||
# you configure your source control system to ignore this file. |
||||
config.example_status_persistence_file_path = "spec/examples.txt" |
||||
|
||||
# Limits the available syntax to the non-monkey patched syntax that is |
||||
# recommended. For more details, see: |
||||
# https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode |
||||
config.disable_monkey_patching! |
||||
|
||||
# Many RSpec users commonly either run the entire suite or an individual |
||||
# file, and it's useful to allow more verbose output when running an |
||||
# individual spec file. |
||||
if config.files_to_run.one? |
||||
# Use the documentation formatter for detailed output, |
||||
# unless a formatter has already been configured |
||||
# (e.g. via a command-line flag). |
||||
config.default_formatter = "doc" |
||||
end |
||||
|
||||
# Print the 10 slowest examples and example groups at the |
||||
# end of the spec run, to help surface which specs are running |
||||
# particularly slow. |
||||
config.profile_examples = 10 |
||||
|
||||
# Run specs in random order to surface order dependencies. If you find an |
||||
# order dependency and want to debug it, you can fix the order by providing |
||||
# the seed, which is printed after each run. |
||||
# --seed 1234 |
||||
config.order = :random |
||||
|
||||
# Seed global randomization in this process using the `--seed` CLI option. |
||||
# Setting this allows you to use `--seed` to deterministically reproduce |
||||
# test failures related to randomization by passing the same `--seed` value |
||||
# as the one that triggered the failure. |
||||
Kernel.srand config.seed |
||||
=end |
||||
end |
@ -1,4 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class CheckControllerTest < ActionController::TestCase |
||||
end |
@ -1,4 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class HttpsControllerTest < ActionController::TestCase |
||||
end |
@ -1,4 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class SiteControllerTest < ActionController::TestCase |
||||
end |
@ -1,4 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class SmtpControllerTest < ActionController::TestCase |
||||
end |
@ -1,4 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class SshControllerTest < ActionController::TestCase |
||||
end |
@ -1,19 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class TlsControllerTest < ActionController::TestCase |
||||
test "should get index" do |
||||
get :index |
||||
assert_response :success |
||||
end |
||||
|
||||
test "should get show" do |
||||
get :show |
||||
assert_response :success |
||||
end |
||||
|
||||
test "should get refresh" do |
||||
get :refresh |
||||
assert_response :success |
||||
end |
||||
|
||||
end |
@ -1,4 +0,0 @@ |
||||
require 'test_helper' |
||||
|
||||
class XmppControllerTest < ActionController::TestCase |
||||
end |
@ -1,3 +0,0 @@ |
||||
ENV['RAILS_ENV'] ||= 'test' |
||||
require File.expand_path('../../config/environment', __FILE__) |
||||
require 'rails/test_help' |
Loading…
Reference in new issue