ContainerImage.Pinniped/internal/testutil/chooseidphtml.go

81 lines
14 KiB
Go
Raw Normal View History

// Copyright 2023 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package testutil
import (
"strings"
"golang.org/x/net/html"
"go.pinniped.dev/internal/here"
)
type ChooseIDPPageExpectedValue struct {
DisplayName string
URL string
}
func spaces(howMany int) string {
return strings.Repeat(" ", howMany)
}
func withNewline(s string) string {
return s + "\n"
}
func htmlEscapedForHTMLTemplate(s string) string {
// The HTML templating package also escapes plus characters, which html.EscapeString does not.
return strings.ReplaceAll(html.EscapeString(s), "+", "+")
}
func ExpectedChooseIDPPageHTML(wantCSS string, wantJS string, wantIDPs []ChooseIDPPageExpectedValue) string {
top := here.Docf(`
<!DOCTYPE html>
<html lang="en">
<head>
<title>Choose Identity Provider</title>
<meta charset="UTF-8">
<style>%s</style>
<script>%s</script>
<link href="data:image/x-icon;base64,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
rel="icon" type="image/x-icon"/>
</head>
<body>
<div class="box" aria-label="choose identity provider form" role="main">
<div class="form-field">
<h1>Choose an identity provider to log in</h1>
</div>
`, wantCSS, wantJS)
noscript := withNewline(spaces(4)+`<noscript>`) +
withNewline(spaces(8)+`<div class="form-field">`) +
withNewline(spaces(12)+`<ul>`) +
withNewline(spaces(16))
for _, wantIDP := range wantIDPs {
noscript += withNewline(spaces(20)+`<li><a href="`+htmlEscapedForHTMLTemplate(wantIDP.URL)+`">`+htmlEscapedForHTMLTemplate(wantIDP.DisplayName)+`</a></li>`) +
withNewline(spaces(16))
}
noscript += withNewline(spaces(12)+`</ul>`) +
withNewline(spaces(8)+`</div>`) +
withNewline(spaces(4)+`</noscript>`)
buttons := withNewline(spaces(4)+`<div id="choose-idp-form-buttons" hidden>`) +
withNewline(spaces(8))
for _, wantIDP := range wantIDPs {
buttons += withNewline(spaces(12)+`<div class="form-field">`) +
withNewline(spaces(16)+`<button data-url="`+htmlEscapedForHTMLTemplate(wantIDP.URL)+`"><span>`+htmlEscapedForHTMLTemplate(wantIDP.DisplayName)+`</span></button>`) +
withNewline(spaces(12)+`</div>`) +
withNewline(spaces(8))
}
buttons += withNewline(spaces(4) + `</div>`)
bottom := here.Doc(`
</div>
</body>
</html>
`)
return top + noscript + buttons + bottom
}