test(suites): load environment into suites (#4762)

* test(suites): load environment into suites

* test(suites): default setup suite

* test(suites): create base suite

* test(suites): fix nil ptr

* test(suites): add logging

* test: fix missing devworkflow path

* refactor: apply suggestions

* refactor: log

* fix: dev workflow requires env file to trigger vite hmr

* fix(suites): fix dynamic configuration in dev workflow for all proxies

* refactor: apply final suggestions

* fix: pass log level to suites

* fix(suites): include pathprefix to prevent react router basename issues

* fix: missing setup logging calls

* fix: gate suite setup funcs

* test: fix lint

* test: fix tmp dir

* fix(suites): fix gitignore of .env.development with vite hmr

Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
pull/4818/head
James Elliott 2023-01-25 15:11:05 +11:00 committed by GitHub
parent 74995264e2
commit 36e817df92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 285 additions and 99 deletions

View File

@ -348,6 +348,8 @@ func runSuiteTests(suiteName string, withEnv bool) error {
cmd.Env = append(cmd.Env, "HEADLESS=y")
}
cmd.Env = append(cmd.Env, "SUITES_LOG_LEVEL="+log.GetLevel().String())
testErr := cmd.Run()
// If the tests failed, run the error hook.

View File

@ -140,9 +140,7 @@ func setupSuite(cmd *cobra.Command, args []string) {
log.Fatal(err)
}
err = s.SetUp(suiteTmpDirectory)
if err != nil {
if err = s.SetUp(suiteTmpDirectory); err != nil {
log.Error("Failure during environment deployment.")
teardownSuite(nil, args)
log.Fatal(err)

View File

@ -2,7 +2,6 @@ package suites
import (
"fmt"
"os"
"github.com/authelia/authelia/v4/internal/configuration/schema"
)
@ -14,9 +13,6 @@ var (
Example3DotCom = "example3.com:8080"
)
// PathPrefix the prefix/url_base of the login portal.
var PathPrefix = os.Getenv("PathPrefix")
// LoginBaseURLFmt the base URL of the login portal for specified baseDomain.
func LoginBaseURLFmt(baseDomain string) string {
if baseDomain == "" {
@ -81,6 +77,8 @@ const (
)
const (
envFileProd = "./web/.env.production"
envFileDev = "./web/.env.development"
namespaceAuthelia = "authelia"
namespaceDashboard = "kubernetes-dashboard"
namespaceKube = "kube-system"

View File

@ -21,11 +21,11 @@ services:
- '${GOPATH}:/go'
labels:
# Traefik 1.x
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api,/locales'
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/.well-known,/api,/locales,/devworkflow,/jwks.json'
- 'traefik.protocol=https'
# Traefik 2.x
- 'traefik.enable=true'
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/.well-known`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/.well-known`) || Host(`login.example.com`) && PathPrefix(`/api`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/api`) || Host(`login.example.com`) && PathPrefix(`/locales`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/locales`) || Host(`login.example.com`) && Path(`/jwks.json`) || Host(`login.example.com`) && Path(`${PathPrefix}/jwks.json`)' # yamllint disable-line rule:line-length
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/.well-known`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/.well-known`) || Host(`login.example.com`) && PathPrefix(`/api`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/api`) || Host(`login.example.com`) && PathPrefix(`/locales`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/locales`) || Host(`login.example.com`) && Path(`/devworkflow`) || Host(`login.example.com`) && Path(`${PathPrefix}/devworkflow`) || Host(`login.example.com`) && Path(`/jwks.json`) || Host(`login.example.com`) && Path(`${PathPrefix}/jwks.json`) || Host(`login.example.com`) && Path(`/static/media/logo.png`) || Host(`login.example.com`) && Path(`${PathPrefix}/static/media/logo.png`)' # yamllint disable-line rule:line-length
- 'traefik.http.routers.authelia_backend.entrypoints=https'
- 'traefik.http.routers.authelia_backend.tls=true'
- 'traefik.http.services.authelia_backend.loadbalancer.server.scheme=https'

View File

@ -29,6 +29,10 @@ login.example.com:8080 {
import tls-transport
}
reverse_proxy /devworkflow authelia-backend:9091 {
import tls-transport
}
reverse_proxy /jwks.json authelia-backend:9091 {
import tls-transport
}

View File

@ -40,6 +40,10 @@ static_resources:
prefix: "/locales/"
route:
cluster: authelia-backend
- match:
path: "/devworkflow"
route:
cluster: authelia-backend
- match:
path: "/jwks.json"
route:

View File

@ -25,6 +25,10 @@ frontend fe_http
bind *:8080 ssl crt /usr/local/etc/haproxy/haproxy.pem
acl api-path path_beg -i /api
acl wellknown-path path_beg -i /.well-known
acl locales-path path_beg -i /locales
acl devworkflow-path path -i -m end /devworkflow
acl jwks-path path -i -m end /jwks.json
acl headers-path path -i -m end /headers
acl host-authelia-portal hdr(host) -i login.example.com:8080
acl protected-frontends hdr(host) -m reg -i ^(?i)(admin|home|public|secure|singlefactor)\.example\.com
@ -54,18 +58,16 @@ frontend fe_http
http-request redirect location https://login.example.com:8080/?rd=%[var(req.scheme)]://%[base]%[var(req.questionmark)]%[query] if protected-frontends !{ var(txn.auth_response_successful) -m bool }
use_backend be_authelia if host-authelia-portal api-path
use_backend be_authelia if host-authelia-portal api-path || wellknown-path || locales-path || devworkflow-path || jwks-path
use_backend fe_authelia if host-authelia-portal !api-path
use_backend be_httpbin if protected-frontends headers-path
use_backend be_mail if { hdr(host) -i mail.example.com:8080 }
use_backend be_protected if protected-frontends
backend be_auth_request
mode http
server proxy 127.0.0.1:8085
listen be_auth_request_proxy
mode http
bind 127.0.0.1:8085
server authelia-backend authelia-backend:9091 resolvers docker ssl verify none
@ -73,6 +75,9 @@ backend be_authelia
server authelia-backend authelia-backend:9091 resolvers docker ssl verify none
backend fe_authelia
option httpchk
http-check expect rstatus ^2
server authelia-frontend authelia-frontend:3000 check resolvers docker
server authelia-backend authelia-backend:9091 check backup resolvers docker ssl verify none

View File

@ -16,7 +16,7 @@ type AvailableMethodsScenario struct {
func NewAvailableMethodsScenario(methods []string) *AvailableMethodsScenario {
return &AvailableMethodsScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
methods: methods,
}
}

View File

@ -16,7 +16,7 @@ type BypassPolicyScenario struct {
func NewBypassPolicyScenario() *BypassPolicyScenario {
return &BypassPolicyScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -19,7 +19,7 @@ type CustomHeadersScenario struct {
func NewCustomHeadersScenario() *CustomHeadersScenario {
return &CustomHeadersScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -18,7 +18,7 @@ type DefaultRedirectionURLScenario struct {
func NewDefaultRedirectionURLScenario() *DefaultRedirectionURLScenario {
return &DefaultRedirectionURLScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -18,7 +18,7 @@ type InactivityScenario struct {
func NewInactivityScenario() *InactivityScenario {
return &InactivityScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -19,7 +19,7 @@ type MultiCookieDomainScenario struct {
// NewMultiCookieDomainScenario returns a new Multi Cookie Domain Test Scenario.
func NewMultiCookieDomainScenario(domain, nextDomain string, remember bool) *MultiCookieDomainScenario {
return &MultiCookieDomainScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
domain: domain,
nextDomain: nextDomain,
remember: remember,

View File

@ -22,7 +22,7 @@ type OIDCScenario struct {
func NewOIDCScenario() *OIDCScenario {
return &OIDCScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -16,7 +16,7 @@ type OneFactorSuite struct {
func New1FAScenario() *OneFactorSuite {
return &OneFactorSuite{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}
@ -49,7 +49,7 @@ func (s *OneFactorSuite) TearDownTest() {
}
func (s *OneFactorSuite) TestShouldAuthorizeSecretAfterOneFactor() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer func() {
cancel()
s.collectScreenshot(ctx.Err(), s.Page)

View File

@ -14,7 +14,7 @@ type PasswordComplexityScenario struct {
}
func NewPasswordComplexityScenario() *PasswordComplexityScenario {
return &PasswordComplexityScenario{RodSuite: new(RodSuite)}
return &PasswordComplexityScenario{RodSuite: NewRodSuite("")}
}
func (s *PasswordComplexityScenario) SetupSuite() {

View File

@ -15,7 +15,7 @@ type RedirectionCheckScenario struct {
func NewRedirectionCheckScenario() *RedirectionCheckScenario {
return &RedirectionCheckScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -16,7 +16,7 @@ type RedirectionURLScenario struct {
func NewRedirectionURLScenario() *RedirectionURLScenario {
return &RedirectionURLScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -16,7 +16,7 @@ type RegulationScenario struct {
func NewRegulationScenario() *RegulationScenario {
return &RegulationScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -14,7 +14,7 @@ type ResetPasswordScenario struct {
}
func NewResetPasswordScenario() *ResetPasswordScenario {
return &ResetPasswordScenario{RodSuite: new(RodSuite)}
return &ResetPasswordScenario{RodSuite: NewRodSuite("")}
}
func (s *ResetPasswordScenario) SetupSuite() {

View File

@ -18,7 +18,7 @@ type SigninEmailScenario struct {
func NewSigninEmailScenario() *SigninEmailScenario {
return &SigninEmailScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -18,7 +18,7 @@ type TwoFactorSuite struct {
func New2FAScenario() *TwoFactorSuite {
return &TwoFactorSuite{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -15,7 +15,7 @@ type UserPreferencesScenario struct {
func NewUserPreferencesScenario() *UserPreferencesScenario {
return &UserPreferencesScenario{
RodSuite: new(RodSuite),
RodSuite: NewRodSuite(""),
}
}

View File

@ -11,7 +11,9 @@ type ActiveDirectorySuite struct {
}
func NewActiveDirectorySuite() *ActiveDirectorySuite {
return &ActiveDirectorySuite{RodSuite: new(RodSuite)}
return &ActiveDirectorySuite{
RodSuite: NewRodSuite(activedirectorySuiteName),
}
}
func (s *ActiveDirectorySuite) Test1FAScenario() {

View File

@ -15,10 +15,14 @@ type BypassAllWebDriverSuite struct {
}
func NewBypassAllWebDriverSuite() *BypassAllWebDriverSuite {
return &BypassAllWebDriverSuite{RodSuite: new(RodSuite)}
return &BypassAllWebDriverSuite{
RodSuite: NewRodSuite(""),
}
}
func (s *BypassAllWebDriverSuite) SetupSuite() {
s.BaseSuite.SetupSuite()
browser, err := StartRod()
if err != nil {
@ -61,11 +65,15 @@ func (s *BypassAllWebDriverSuite) TestShouldAccessPublicResource() {
}
type BypassAllSuite struct {
suite.Suite
*BaseSuite
}
func NewBypassAllSuite() *BypassAllSuite {
return &BypassAllSuite{}
return &BypassAllSuite{
BaseSuite: &BaseSuite{
Name: bypassAllSuiteName,
},
}
}
func (s *BypassAllSuite) TestBypassAllWebDriverSuite() {

View File

@ -11,7 +11,9 @@ type CaddySuite struct {
}
func NewCaddySuite() *CaddySuite {
return &CaddySuite{RodSuite: new(RodSuite)}
return &CaddySuite{
RodSuite: NewRodSuite(caddySuiteName),
}
}
func (s *CaddySuite) Test1FAScenario() {

View File

@ -23,10 +23,18 @@ type CLISuite struct {
}
func NewCLISuite() *CLISuite {
return &CLISuite{CommandSuite: new(CommandSuite)}
return &CLISuite{
CommandSuite: &CommandSuite{
BaseSuite: &BaseSuite{
Name: cliSuiteName,
},
},
}
}
func (s *CLISuite) SetupSuite() {
s.BaseSuite.SetupSuite()
dockerEnvironment := NewDockerEnvironment([]string{
"internal/suites/docker-compose.yml",
"internal/suites/CLI/docker-compose.yml",

View File

@ -11,7 +11,9 @@ type DockerSuite struct {
}
func NewDockerSuite() *DockerSuite {
return &DockerSuite{RodSuite: new(RodSuite)}
return &DockerSuite{
RodSuite: NewRodSuite(dockerSuiteName),
}
}
func (s *DockerSuite) Test1FAScenario() {

View File

@ -20,7 +20,9 @@ type DuoPushWebDriverSuite struct {
}
func NewDuoPushWebDriverSuite() *DuoPushWebDriverSuite {
return &DuoPushWebDriverSuite{RodSuite: new(RodSuite)}
return &DuoPushWebDriverSuite{
RodSuite: NewRodSuite(""),
}
}
func (s *DuoPushWebDriverSuite) SetupSuite() {
@ -386,10 +388,12 @@ type DuoPushDefaultRedirectionSuite struct {
}
func NewDuoPushDefaultRedirectionSuite() *DuoPushDefaultRedirectionSuite {
return &DuoPushDefaultRedirectionSuite{RodSuite: new(RodSuite)}
return &DuoPushDefaultRedirectionSuite{RodSuite: NewRodSuite(duoPushSuiteName)}
}
func (s *DuoPushDefaultRedirectionSuite) SetupSuite() {
s.BaseSuite.SetupSuite()
browser, err := StartRod()
if err != nil {
@ -444,11 +448,15 @@ func (s *DuoPushDefaultRedirectionSuite) TestUserIsRedirectedToDefaultURL() {
}
type DuoPushSuite struct {
suite.Suite
*BaseSuite
}
func NewDuoPushSuite() *DuoPushSuite {
return &DuoPushSuite{}
return &DuoPushSuite{
BaseSuite: &BaseSuite{
Name: duoPushSuiteName,
},
}
}
func (s *DuoPushSuite) TestDuoPushWebDriverSuite() {

View File

@ -11,7 +11,9 @@ type EnvoySuite struct {
}
func NewEnvoySuite() *EnvoySuite {
return &EnvoySuite{RodSuite: new(RodSuite)}
return &EnvoySuite{
RodSuite: NewRodSuite(envoySuiteName),
}
}
func (s *EnvoySuite) Test1FAScenario() {

View File

@ -11,7 +11,9 @@ type HAProxySuite struct {
}
func NewHAProxySuite() *HAProxySuite {
return &HAProxySuite{RodSuite: new(RodSuite)}
return &HAProxySuite{
RodSuite: NewRodSuite(haproxySuiteName),
}
}
func (s *HAProxySuite) Test1FAScenario() {

View File

@ -17,10 +17,14 @@ type HighAvailabilityWebDriverSuite struct {
}
func NewHighAvailabilityWebDriverSuite() *HighAvailabilityWebDriverSuite {
return &HighAvailabilityWebDriverSuite{RodSuite: new(RodSuite)}
return &HighAvailabilityWebDriverSuite{
RodSuite: NewRodSuite(""),
}
}
func (s *HighAvailabilityWebDriverSuite) SetupSuite() {
s.BaseSuite.SetupSuite()
browser, err := StartRod()
if err != nil {
@ -183,7 +187,9 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldKeepSessionAfterAutheliaResta
}
var UserJohn = "john"
var UserBob = "bob"
var UserHarry = "harry"
var Users = []string{UserJohn, UserBob, UserHarry}
@ -263,11 +269,15 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldVerifyAccessControl() {
}
type HighAvailabilitySuite struct {
suite.Suite
*BaseSuite
}
func NewHighAvailabilitySuite() *HighAvailabilitySuite {
return &HighAvailabilitySuite{}
return &HighAvailabilitySuite{
BaseSuite: &BaseSuite{
Name: highAvailabilitySuiteName,
},
}
}
func DoGetWithAuth(t *testing.T, username, password string) int {

View File

@ -11,7 +11,9 @@ type KubernetesSuite struct {
}
func NewKubernetesSuite() *KubernetesSuite {
return &KubernetesSuite{RodSuite: new(RodSuite)}
return &KubernetesSuite{
RodSuite: NewRodSuite(kubernetesSuiteName),
}
}
func (s *KubernetesSuite) Test1FAScenario() {

View File

@ -11,7 +11,9 @@ type LDAPSuite struct {
}
func NewLDAPSuite() *LDAPSuite {
return &LDAPSuite{RodSuite: new(RodSuite)}
return &LDAPSuite{
RodSuite: NewRodSuite(ldapSuiteName),
}
}
func (s *LDAPSuite) Test1FAScenario() {

View File

@ -11,7 +11,9 @@ type MariaDBSuite struct {
}
func NewMariaDBSuite() *MariaDBSuite {
return &MariaDBSuite{RodSuite: new(RodSuite)}
return &MariaDBSuite{
RodSuite: NewRodSuite(mariadbSuiteName),
}
}
func (s *MariaDBSuite) Test1FAScenario() {

View File

@ -7,11 +7,15 @@ import (
)
func NewMultiCookieDomainSuite() *MultiCookieDomainSuite {
return &MultiCookieDomainSuite{}
return &MultiCookieDomainSuite{
BaseSuite: &BaseSuite{
Name: multiCookieDomainSuiteName,
},
}
}
type MultiCookieDomainSuite struct {
suite.Suite
*BaseSuite
}
func (s *MultiCookieDomainSuite) TestMultiCookieDomainFirstDomainScenario() {

View File

@ -11,7 +11,9 @@ type MySQLSuite struct {
}
func NewMySQLSuite() *MySQLSuite {
return &MySQLSuite{RodSuite: new(RodSuite)}
return &MySQLSuite{
RodSuite: NewRodSuite(mysqlSuiteName),
}
}
func (s *MySQLSuite) Test1FAScenario() {

View File

@ -10,11 +10,15 @@ import (
)
type NetworkACLSuite struct {
suite.Suite
*BaseSuite
}
func NewNetworkACLSuite() *NetworkACLSuite {
return &NetworkACLSuite{}
return &NetworkACLSuite{
BaseSuite: &BaseSuite{
Name: networkACLSuiteName,
},
}
}
func (s *NetworkACLSuite) TestShouldAccessSecretUpon2FA() {

View File

@ -11,7 +11,9 @@ type OIDCSuite struct {
}
func NewOIDCSuite() *OIDCSuite {
return &OIDCSuite{RodSuite: new(RodSuite)}
return &OIDCSuite{
RodSuite: NewRodSuite(oidcSuiteName),
}
}
func (s *OIDCSuite) TestOIDCScenario() {

View File

@ -11,7 +11,9 @@ type OIDCTraefikSuite struct {
}
func NewOIDCTraefikSuite() *OIDCTraefikSuite {
return &OIDCTraefikSuite{RodSuite: new(RodSuite)}
return &OIDCTraefikSuite{
RodSuite: NewRodSuite(oidcTraefikSuiteName),
}
}
func (s *OIDCTraefikSuite) TestOIDCScenario() {

View File

@ -11,18 +11,18 @@ import (
)
type OneFactorOnlySuite struct {
suite.Suite
}
type OneFactorOnlyWebSuite struct {
*RodSuite
}
func NewOneFactorOnlyWebSuite() *OneFactorOnlyWebSuite {
return &OneFactorOnlyWebSuite{RodSuite: new(RodSuite)}
func NewOneFactorOnlySuite() *OneFactorOnlySuite {
return &OneFactorOnlySuite{
RodSuite: NewRodSuite(oneFactorOnlySuiteName),
}
}
func (s *OneFactorOnlyWebSuite) SetupSuite() {
func (s *OneFactorOnlySuite) SetupSuite() {
s.BaseSuite.SetupSuite()
browser, err := StartRod()
if err != nil {
@ -32,7 +32,7 @@ func (s *OneFactorOnlyWebSuite) SetupSuite() {
s.RodSession = browser
}
func (s *OneFactorOnlyWebSuite) TearDownSuite() {
func (s *OneFactorOnlySuite) TearDownSuite() {
err := s.RodSession.Stop()
if err != nil {
@ -40,18 +40,18 @@ func (s *OneFactorOnlyWebSuite) TearDownSuite() {
}
}
func (s *OneFactorOnlyWebSuite) SetupTest() {
func (s *OneFactorOnlySuite) SetupTest() {
s.Page = s.doCreateTab(s.T(), HomeBaseURL)
s.verifyIsHome(s.T(), s.Page)
}
func (s *OneFactorOnlyWebSuite) TearDownTest() {
func (s *OneFactorOnlySuite) TearDownTest() {
s.collectCoverage(s.Page)
s.MustClose()
}
// No target url is provided, then the user should be redirect to the default url.
func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURL() {
func (s *OneFactorOnlySuite) TestShouldRedirectUserToDefaultURL() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer func() {
cancel()
@ -63,7 +63,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURL() {
}
// Unsafe URL is provided, then the user should be redirect to the default url.
func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURLWhenURLIsUnsafe() {
func (s *OneFactorOnlySuite) TestShouldRedirectUserToDefaultURLWhenURLIsUnsafe() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer func() {
cancel()
@ -75,7 +75,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURLWhenURLIsUnsaf
}
// When use logged in and visit the portal again, she gets redirect to the authenticated view.
func (s *OneFactorOnlyWebSuite) TestShouldDisplayAuthenticatedView() {
func (s *OneFactorOnlySuite) TestShouldDisplayAuthenticatedView() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer func() {
cancel()
@ -88,7 +88,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldDisplayAuthenticatedView() {
s.verifyIsAuthenticatedPage(s.T(), s.Context(ctx))
}
func (s *OneFactorOnlyWebSuite) TestShouldRedirectAlreadyAuthenticatedUser() {
func (s *OneFactorOnlySuite) TestShouldRedirectAlreadyAuthenticatedUser() {
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer func() {
cancel()
@ -103,7 +103,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldRedirectAlreadyAuthenticatedUser() {
s.verifyURLIs(s.T(), s.Context(ctx), "https://singlefactor.example.com:8080/secret.html")
}
func (s *OneFactorOnlyWebSuite) TestShouldNotRedirectAlreadyAuthenticatedUserToUnsafeURL() {
func (s *OneFactorOnlySuite) TestShouldNotRedirectAlreadyAuthenticatedUserToUnsafeURL() {
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer func() {
cancel()
@ -118,14 +118,10 @@ func (s *OneFactorOnlyWebSuite) TestShouldNotRedirectAlreadyAuthenticatedUserToU
s.verifyNotificationDisplayed(s.T(), s.Context(ctx), "Redirection was determined to be unsafe and aborted. Ensure the redirection URL is correct.")
}
func (s *OneFactorOnlySuite) TestWeb() {
suite.Run(s.T(), NewOneFactorOnlyWebSuite())
}
func TestOneFactorOnlySuite(t *testing.T) {
if testing.Short() {
t.Skip("skipping suite test in short mode")
}
suite.Run(t, new(OneFactorOnlySuite))
suite.Run(t, NewOneFactorOnlySuite())
}

View File

@ -11,7 +11,9 @@ type PathPrefixSuite struct {
}
func NewPathPrefixSuite() *PathPrefixSuite {
return &PathPrefixSuite{RodSuite: new(RodSuite)}
return &PathPrefixSuite{
RodSuite: NewRodSuite(pathPrefixSuiteName),
}
}
func (s *PathPrefixSuite) Test1FAScenario() {

View File

@ -11,7 +11,9 @@ type PostgresSuite struct {
}
func NewPostgresSuite() *PostgresSuite {
return &PostgresSuite{RodSuite: new(RodSuite)}
return &PostgresSuite{
RodSuite: NewRodSuite(postgresSuiteName),
}
}
func (s *PostgresSuite) Test1FAScenario() {

View File

@ -11,7 +11,9 @@ type ShortTimeoutsSuite struct {
}
func NewShortTimeoutsSuite() *ShortTimeoutsSuite {
return &ShortTimeoutsSuite{RodSuite: new(RodSuite)}
return &ShortTimeoutsSuite{
RodSuite: NewRodSuite(shortTimeoutsSuiteName),
}
}
func (s *ShortTimeoutsSuite) TestDefaultRedirectionURLScenario() {

View File

@ -22,10 +22,14 @@ type StandaloneWebDriverSuite struct {
}
func NewStandaloneWebDriverSuite() *StandaloneWebDriverSuite {
return &StandaloneWebDriverSuite{RodSuite: new(RodSuite)}
return &StandaloneWebDriverSuite{
RodSuite: NewRodSuite(""),
}
}
func (s *StandaloneWebDriverSuite) SetupSuite() {
s.BaseSuite.SetupSuite()
browser, err := StartRod()
if err != nil {
@ -169,11 +173,15 @@ func (s *StandaloneWebDriverSuite) TestShouldCheckUserIsAskedToRegisterDevice()
}
type StandaloneSuite struct {
suite.Suite
*BaseSuite
}
func NewStandaloneSuite() *StandaloneSuite {
return &StandaloneSuite{}
return &StandaloneSuite{
BaseSuite: &BaseSuite{
Name: standaloneSuiteName,
},
}
}
func (s *StandaloneSuite) TestShouldRespectMethodsACL() {

View File

@ -14,7 +14,9 @@ type Traefik2Suite struct {
}
func NewTraefik2Suite() *Traefik2Suite {
return &Traefik2Suite{RodSuite: new(RodSuite)}
return &Traefik2Suite{
RodSuite: NewRodSuite(traefik2SuiteName),
}
}
func (s *Traefik2Suite) Test1FAScenario() {

View File

@ -11,7 +11,9 @@ type TraefikSuite struct {
}
func NewTraefikSuite() *TraefikSuite {
return &TraefikSuite{RodSuite: new(RodSuite)}
return &TraefikSuite{
RodSuite: NewRodSuite(traefikSuiteName),
}
}
func (s *TraefikSuite) Test1FAScenario() {

View File

@ -5,17 +5,31 @@ import (
"github.com/stretchr/testify/suite"
)
func NewRodSuite(name string) *RodSuite {
return &RodSuite{
BaseSuite: &BaseSuite{
Name: name,
},
}
}
// RodSuite is a go-rod suite.
type RodSuite struct {
suite.Suite
*BaseSuite
*RodSession
*rod.Page
}
type BaseSuite struct {
suite.Suite
Name string
}
// CommandSuite is a command line interface suite.
type CommandSuite struct {
suite.Suite
*BaseSuite
testArg string //nolint:structcheck // TODO: Remove when bug fixed: https://github.com/golangci/golangci-lint/issues/537.
coverageArg string //nolint:structcheck // TODO: Remove when bug fixed: https://github.com/golangci/golangci-lint/issues/537.

View File

@ -1,12 +1,12 @@
package suites
import (
"bufio"
"context"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
@ -16,6 +16,7 @@ import (
"github.com/go-rod/rod"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
)
var browserPaths = []string{"/usr/bin/chromium-browser", "/usr/bin/chromium"}
@ -52,8 +53,8 @@ func GetBrowserPath() (path string, err error) {
// GetLoginBaseURL returns the URL of the login portal and the path prefix if specified.
func GetLoginBaseURL(baseDomain string) string {
if PathPrefix != "" {
return LoginBaseURLFmt(baseDomain) + PathPrefix
if pathPrefix := os.Getenv("PathPrefix"); pathPrefix != "" {
return LoginBaseURLFmt(baseDomain) + pathPrefix
}
return LoginBaseURLFmt(baseDomain)
@ -84,6 +85,87 @@ func (rs *RodSession) collectCoverage(page *rod.Page) {
}
}
func (s *BaseSuite) SetupSuite() {
s.SetupLogging()
s.SetupEnvironment()
}
func (s *BaseSuite) SetupLogging() {
if os.Getenv("SUITE_SETUP_LOGGING") == t {
return
}
var (
level string
ok bool
)
if level, ok = os.LookupEnv("SUITES_LOG_LEVEL"); !ok {
return
}
l, err := log.ParseLevel(level)
s.NoError(err)
log.SetLevel(l)
log.SetFormatter(&log.TextFormatter{
ForceColors: true,
})
s.T().Setenv("SUITE_SETUP_LOGGING", t)
}
func (s *BaseSuite) SetupEnvironment() {
if s.Name == "" || os.Getenv("SUITE_SETUP_ENVIRONMENT") == t {
return
}
log.Debugf("Checking Suite %s for .env file", s.Name)
path := filepath.Join(s.Name, ".env")
var (
info os.FileInfo
err error
)
path, err = filepath.Abs(path)
s.Require().NoError(err)
if info, err = os.Stat(path); err != nil {
s.Assert().True(os.IsNotExist(err))
log.Debugf("Suite %s does not have an .env file or it can't be read: %v", s.Name, err)
return
}
s.Require().False(info.IsDir())
log.Debugf("Suite %s does have an .env file at path: %s", s.Name, path)
var file *os.File
file, err = os.Open(path)
s.Require().NoError(err)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
v := strings.Split(scanner.Text(), "=")
s.Require().Len(v, 2)
s.T().Setenv(v[0], v[1])
}
s.T().Setenv("SUITE_SETUP_ENVIRONMENT", t)
}
func (rs *RodSession) collectScreenshot(err error, page *rod.Page) {
if err == context.DeadlineExceeded && os.Getenv("CI") == t {
base := "/buildkite/screenshots"
@ -140,7 +222,7 @@ func fixCoveragePath(path string, file os.FileInfo, err error) error {
}
// getEnvInfoFromURL gets environments variables for specified cookie domain
// this func makes a http call to https://login.<domain>/override and is only useful for suite tests.
// this func makes a http call to https://login.<domain>/devworkflow and is only useful for suite tests.
func getDomainEnvInfo(domain string) (map[string]string, error) {
info := make(map[string]string)
@ -186,18 +268,12 @@ func getDomainEnvInfo(domain string) (map[string]string, error) {
// generateDevEnvFile generates web/.env.development based on opts.
func generateDevEnvFile(opts map[string]string) error {
wd, _ := os.Getwd()
path := strings.TrimSuffix(wd, "internal/suites")
src := fmt.Sprintf("%s/web/.env.production", path)
dst := fmt.Sprintf("%s/web/.env.development", path)
tmpl, err := template.ParseFiles(src)
tmpl, err := template.ParseFiles(envFileProd)
if err != nil {
return err
}
file, _ := os.Create(dst)
file, _ := os.Create(envFileDev)
defer file.Close()
if err := tmpl.Execute(file, opts); err != nil {
@ -210,10 +286,15 @@ func generateDevEnvFile(opts map[string]string) error {
// updateDevEnvFileForDomain updates web/.env.development.
// this function only affects local dev environments.
func updateDevEnvFileForDomain(domain string, setup bool) error {
if os.Getenv("CI") == "true" {
if os.Getenv("CI") == t {
return nil
}
if _, err := os.Stat(envFileDev); err != nil && os.IsNotExist(err) {
file, _ := os.Create(envFileDev)
file.Close()
}
info, err := getDomainEnvInfo(domain)
if err != nil {
return err

View File

@ -36,7 +36,9 @@ func TestShouldReturnErrWhenX509DirectoryNotExist(t *testing.T) {
}
func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) {
pool, warnings, errors := NewX509CertPool("/tmp")
dir := t.TempDir()
pool, warnings, errors := NewX509CertPool(dir)
assert.NotNil(t, pool)
if runtime.GOOS == windows {