Documentation
¶
Overview ¶
Package plugintest is the test kit that ships with the filex plugin SDK.
A plugin is a wasm module filex loads, so the obvious way to test one is to build it and install it — which is slow, needs a host, and happens after the mistake is already in the module. plugintest runs the plugin's own Go functions in-process, behind a fake filex, so `go test` answers the questions that matter before `plugin.wasm` exists:
- does the action do the right thing, and does it degrade when a permission is missing or an engine is absent?
- is every screen drawable by filex's renderer — known node types, a readable choice instead of a dropdown, one primary button per step, conditions that point at fields that exist?
- does every string carry every language the manifest promises?
- did a screen change shape without anybody noticing (golden screens)?
The shape of a test ¶
func harness(t *testing.T) *plugintest.Harness {
h := plugintest.New(myapp.Plugin()) // manifest + actions + views
h.Host.InstallEngine("ffmpeg") // what this fake server has
return h
}
func TestOptionsScreen(t *testing.T) {
h := harness(t)
s, err := h.Open("options", plugintest.File{Name: "clip.mov"})
if err != nil {
t.Fatal(err)
}
plugintest.CheckSurface(t, h.Manifest(), s) // structure
plugintest.CheckLanguages(t, h.Manifest(), s) // every declared language
plugintest.Golden(t, "options", s) // shape, vs testdata/golden
}
The fake host ¶
Host is filex's host side in memory: files, settings, per-file state, locks, engines, signing, notifications, mail, HTTP and shares. It uses the manifest's permissions as the administrator's grants and answers a call it was not granted with the real code (`permission_denied`), and it refuses from a screen what only an action job may do. Anything else would make the kit lie: the plugin would pass its tests and fail on a real instance.
What it cannot do ¶
The host functions in pluginkit only answer inside wasm; off-wasm they return ErrNotWasm. So a plugin reaches the fake host the way it reaches the real one in tests everywhere else — through a small interface it takes as a parameter (see the `Host` interface in filex-convert's internal/job). *Host satisfies such an interface method-for-method, with the same names and signatures as pluginkit's own functions.
Index ¶
- Variables
- func AsText(v any, langs []string) (wire.Text, bool)
- func CheckLanguages(t TB, m wire.Manifest, s *wire.Surface)
- func CheckLocaleParity(t TB, byLocale map[string]*wire.Surface)
- func CheckLocaleParityOpts(t TB, byLocale map[string]*wire.Surface, opts LangOpts)
- func CheckManifest(t TB, m wire.Manifest)
- func CheckManifestLanguages(t TB, m wire.Manifest)
- func CheckRegistered(t TB, p *pluginkit.Plugin)
- func CheckSchedule(m wire.Manifest, in *wire.TickInput, out *wire.TickOutput) error
- func CheckSurface(t TB, m wire.Manifest, s *wire.Surface)
- func ChoiceValues(s *wire.Surface, key string) []string
- func Choices(s *wire.Surface, key string) ([]wire.FieldOption, bool)
- func Code(err error) string
- func Field(s *wire.Surface, key string) (wire.Field, bool)
- func FieldsOf(n wire.Node) []wire.Field
- func Forms(s *wire.Surface) []wire.Node
- func Golden(t TB, name string, v any)
- func GoldenWith(t TB, name string, v any, scrub func([]byte) []byte)
- func HiddenKeys(fields []wire.Field, values map[string]any) []string
- func IsCode(err error, code string) bool
- func Languages(m wire.Manifest) []string
- func Nodes(s *wire.Surface, typ string) []wire.Node
- func PrimaryAction(s *wire.Surface) (wire.SurfaceAction, bool)
- func RequiredKeys(fields []wire.Field, values map[string]any) []string
- func Submitted(fields []wire.Field, values map[string]any) map[string]any
- func Updating() bool
- func ValuesOf(n wire.Node) map[string]any
- func VisibleKeys(fields []wire.Field, values map[string]any) []string
- func WalkNodes(nodes []wire.Node, fn func(where string, n wire.Node))
- type EngineCall
- type File
- type Finding
- type Harness
- func (h *Harness) Act(viewID, actionID string, state, values map[string]any) (*wire.Surface, error)
- func (h *Harness) Change(viewID string, state, values map[string]any) (*wire.Surface, error)
- func (h *Harness) Do(actionID string, params map[string]any, files ...File) (*wire.ActionRunOutput, error)
- func (h *Harness) Event(event string, files ...File) *wire.ViewEventInput
- func (h *Harness) InLocales(viewID string, ev *wire.ViewEventInput) (map[string]*wire.Surface, error)
- func (h *Harness) Input(actionID string, files ...File) *wire.ActionRunInput
- func (h *Harness) Languages() []string
- func (h *Harness) Manifest() wire.Manifest
- func (h *Harness) Open(viewID string, files ...File) (*wire.Surface, error)
- func (h *Harness) OpenInLocales(viewID string, files ...File) (map[string]*wire.Surface, error)
- func (h *Harness) Page(pageID, token string, ev *wire.ViewEventInput) (*wire.Surface, error)
- func (h *Harness) Queue(s *wire.Surface, files ...File) (*wire.ActionRunOutput, error)
- func (h *Harness) Run(actionID string, in *wire.ActionRunInput) (*wire.ActionRunOutput, error)
- func (h *Harness) Select(files ...File) []wire.FileRef
- func (h *Harness) Selection() []wire.FileRef
- func (h *Harness) Submit(viewID string, state, values map[string]any) (*wire.Surface, error)
- func (h *Harness) Tick(in *wire.TickInput) (*wire.TickOutput, error)
- func (h *Harness) TickInput(now time.Time) *wire.TickInput
- func (h *Harness) UICall(viewID, method string, params any, files ...File) (*wire.UICallOutput, error)
- func (h *Harness) View(viewID string, ev *wire.ViewEventInput) (*wire.Surface, error)
- func (h *Harness) Wake(now time.Time) (*wire.TickOutput, error)
- type Host
- func (h *Host) AddInput(f File) wire.FileRef
- func (h *Host) AddUser(u pluginkit.User)
- func (h *Host) Artefact(name string, data []byte) wire.OutputRef
- func (h *Host) AssetFetch(url, sum string, maxBytes int64) (*pluginkit.Asset, error)
- func (h *Host) Bytes(ref string) ([]byte, bool)
- func (h *Host) CallSettings() map[string]string
- func (h *Host) CertIssue(commonName, email string, days int) (*pluginkit.IssuedCert, error)
- func (h *Host) EngineAvailable(name string) bool
- func (h *Host) EngineRun(req pluginkit.EngineRequest) (*pluginkit.EngineResult, error)
- func (h *Host) EnterJob()
- func (h *Host) EnterScreen()
- func (h *Host) EnterShare(token string)
- func (h *Host) FileLock(ref string, ttlDays int, reason string) (time.Time, error)
- func (h *Host) FileLockMessage(ref string, ttlDays int, key string, args map[string]string) (time.Time, error)
- func (h *Host) FileUnlock(ref string) error
- func (h *Host) HTTPDo(req pluginkit.HTTPRequest) (*pluginkit.HTTPResponse, error)
- func (h *Host) HostSign(keyRef string, digest []byte) ([]byte, error)
- func (h *Host) HostSignInfo() (*pluginkit.SignInfo, error)
- func (h *Host) InputSize(ref string) int64
- func (h *Host) InstallEngine(names ...string)
- func (h *Host) InstalledEngines() map[string]bool
- func (h *Host) Key(ref string) (*IssuedKey, bool)
- func (h *Host) KeyDestroy(keyRef string) error
- func (h *Host) LockReason(ref string) wire.Text
- func (h *Host) Locked(ref string) (time.Time, bool)
- func (h *Host) Log(level, msg string)
- func (h *Host) MailSend(to, subject, body string) error
- func (h *Host) MailSendIn(lang, to, subject, body string) error
- func (h *Host) NewSigner(issued *pluginkit.IssuedCert) (*Signer, error)
- func (h *Host) NotifySend(n pluginkit.Notice) (int64, error)
- func (h *Host) Outputs() []wire.OutputRef
- func (h *Host) PlatformSeal() (*pluginkit.IssuedCert, error)
- func (h *Host) Progress(done, total int64, message string)
- func (h *Host) ReadInput(ref string) ([]byte, error)
- func (h *Host) SetSetting(key, value string)
- func (h *Host) Setting(key string) (string, bool, error)
- func (h *Host) ShareByToken(token string) (*Share, bool)
- func (h *Host) ShareCreate(req pluginkit.PageCreate) (*pluginkit.PageCreated, error)
- func (h *Host) ShareRevoke(token string) error
- func (h *Host) ShareState(token string, out any) error
- func (h *Host) ShareStateSet(token string, state any) error
- func (h *Host) Shares() []*Share
- func (h *Host) State(ref, key string) (string, bool)
- func (h *Host) StateDelete(ref, key string) error
- func (h *Host) StateGet(ref, key string) (string, bool, error)
- func (h *Host) StateSet(ref, key, value string) error
- func (h *Host) UsersLookup(q string) ([]pluginkit.User, error)
- func (h *Host) WriteOutput(name string, data []byte) (wire.OutputRef, error)
- type IssuedKey
- type LangOpts
- type Mail
- type ProgressLine
- type Report
- func InspectLanguages(m wire.Manifest, s *wire.Surface, opts LangOpts) Report
- func InspectLocaleParity(byLocale map[string]*wire.Surface, opts LangOpts) Report
- func InspectManifest(m wire.Manifest) Report
- func InspectManifestLanguages(m wire.Manifest, opts LangOpts) Report
- func InspectRegistered(p *pluginkit.Plugin) Report
- func InspectSurface(m wire.Manifest, s *wire.Surface) Report
- type Severity
- type Share
- type Signer
- type TB
- type TextAt
Constants ¶
This section is empty.
Variables ¶
var FieldTypes = map[string]bool{ "string": true, "password": true, "int": true, "bool": true, "select": true, "text": true, "date": true, }
FieldTypes are the input types a form field may declare.
var GoldenDir = filepath.Join("testdata", "golden")
GoldenDir is where the stored screens live, relative to the test's package directory.
var HumanKeys = map[string]bool{ "label": true, "help": true, "placeholder": true, "text": true, "title": true, "toast": true, "message": true, "empty": true, "hint": true, "description": true, "summary": true, "note": true, "caption": true, "subject": true, "heading": true, "reason": true, }
HumanKeys are the property names that hold a string a person reads. The locale comparison only looks at these (and at every Text): an id, a key or an option's value is the same in every language by design, and warning about those would bury the one line that matters.
var KnownEngines = map[string]bool{ "ffmpeg": true, "imagemagick": true, "libreoffice": true, "ghostscript": true, "poppler": true, "rsvg": true, }
KnownEngines are the engines a plugin may ask for.
var LayoutNodes = map[string]bool{"row": true}
LayoutNodes are the node types that may carry children.
var NodeTypes = map[string]bool{ "text": true, "divider": true, "row": true, "form": true, "steps": true, "list": true, "progress": true, "people-picker": true, "pin-input": true, "file-chooser": true, "preview": true, "pdf-fields": true, "signature-pad": true, }
NodeTypes is filex's node catalogue — the components a surface may ask for. A type that is not here is drawn by nothing: the screen comes up with a hole in it. Kept in step with the table in docs/PLUGIN-KIT.md.
var Permissions = map[string]bool{ "files:read": true, "files:write": true, "files:lock": true, "sign": true, "mail:send": true, "notify:send": true, "users:lookup": true, "settings": true, "state": true, "public_pages": true, "schedule": true, }
Permissions is the closed set a manifest may ask for; the parameterised ones (`http:<host>`, `engines:<name>`) are checked by prefix. `events:<name>` is refused — see manifest.go. ⚠ It must track wasmplugin's own set (internal/wasmplugin/permissions.go). `schedule` was missing here for a release after the host accepted it, so a plugin asking for the hourly wake-up had its manifest REFUSED by its own tests while the server installed it happily — the kit, not the app, was wrong. Add the name here in the same change that adds it there.
Functions ¶
func AsText ¶
AsText recognises a Text: every key is a language tag, every value is a string, and it either carries `en` (required everywhere) or speaks only languages the plugin declared. The second condition is what keeps a row of cells like {"id": "…"} from being read as Indonesian.
func CheckLanguages ¶
CheckLanguages fails t when a Text on the screen is missing a language the manifest promised.
func CheckLocaleParity ¶
CheckLocaleParity fails t when the same screen, drawn once per declared language, is not the same screen: a section only one language has, or a string that is empty in one. Strings that came out identical in two languages are reported as warnings — that is what a missing translation looks like from the outside.
func CheckLocaleParityOpts ¶
CheckLocaleParityOpts is CheckLocaleParity with an allowlist for strings that are the same in every language on purpose (format names, brands).
func CheckManifest ¶
CheckManifest measures the manifest against what filex refuses at install, and fails t on a breach.
func CheckManifestLanguages ¶
CheckManifestLanguages fails t when a Text in the manifest itself — the plugin's label, an action's label, a public page's title — is missing a declared language. This is the one the host also checks at install; a test says so before the install does.
func CheckRegistered ¶
CheckRegistered measures the plugin against its own manifest: every action, view and public page the manifest advertises has a function behind it, and nothing is registered that the manifest never declared. A menu row that opens a screen nobody wrote is the failure this catches.
func CheckSchedule ¶
CheckSchedule applies the bounds filex publishes to an answer, and returns every complaint at once rather than the first.
It is a warning, not the enforcement — the host is what refuses — but it is the same set of numbers (wire.Schedule*) and the same shapes, checked where a failing `go test` costs seconds instead of an hour of wall clock.
func CheckSurface ¶
CheckSurface runs every structural rule against a screen and fails t on a breach. Warnings are logged.
func ChoiceValues ¶
ChoiceValues is Choices reduced to the option values.
func Choices ¶
Choices answers the options a select renders as buttons. It is how a test reads a picker without knowing how it is drawn: `len(Choices(s, "target"))` is the number of buttons the person sees, and their labels are what the buttons say. The second result is false when there is no such field or it is not a select.
func FieldsOf ¶
FieldsOf reads a form node's fields, whether the plugin built them as wire.Field values or as plain maps.
func Golden ¶
Golden compares v (a surface, a manifest, an action's output — anything that marshals) against testdata/golden/<name>.json. With -update it writes the file instead.
func GoldenWith ¶
GoldenWith is Golden with a chance to scrub the volatile parts — a token, a timestamp, a temporary path — out of the JSON before it is compared, so the stored screen stays stable.
func HiddenKeys ¶
HiddenKeys is the other half of VisibleKeys: the fields `show_when` is keeping off the screen. The host drops their values before a job runs.
func PrimaryAction ¶
func PrimaryAction(s *wire.Surface) (wire.SurfaceAction, bool)
PrimaryAction answers the step's one primary button.
func RequiredKeys ¶
RequiredKeys is the set of fields that must be filled for those values (`required`, plus `required_when` where the rule holds).
func Submitted ¶
Submitted is what the host would hand the job: the values of the fields that are visible, with everything else dropped — the same rule the host re-applies at submit, so a test can prove a hidden box cannot smuggle a value through.
func Updating ¶
func Updating() bool
Updating reports whether this run rewrites the golden screens (-update, or PLUGINTEST_UPDATE=1).
func VisibleKeys ¶
VisibleKeys is the set of field keys a person can see for those values, after `show_when` has had its say.
Types ¶
type EngineCall ¶
type EngineCall struct {
Request pluginkit.EngineRequest
Result *pluginkit.EngineResult
Err error
}
EngineCall is one engine_run call, recorded in order.
type File ¶
type File struct {
Name string
Data []byte
Mime string
// Path is the adapter-qualified spelling (`docs://a/b.pdf`); the
// harness invents one when it is empty.
Path string
// Rel is the storage-relative path; defaults to Name.
Rel string
// ReadOnly puts the file on a storage that takes no writes
// (wire.FileRef.ReadOnly).
ReadOnly bool
}
File is one file handed to a call.
type Harness ¶
type Harness struct {
// Plugin is what the module registers with pluginkit.Run.
Plugin *pluginkit.Plugin
// Host is the fake instance. Wire it before a call: settings, engines,
// directory entries, scripted engine answers.
Host *Host
// Locale is the language a call carries when the event does not name
// one (default "en").
Locale string
// Actor is the person the call runs as. By default an administrator, and
// so holding every one of the manifest's `user_permissions`
// (Actor.Permissions), as filex decides it; clear Permissions (or set
// the ids a test needs) to draw a screen for somebody who holds fewer.
Actor wire.Actor
// contains filtered or unexported fields
}
Harness is a plugin under test with a fake filex behind it.
func New ¶
New builds a harness around a registered plugin. For the manifest-only checks a bare `&pluginkit.Plugin{Manifest: m}` is enough.
func NewFor ¶
NewFor is New for a plugin that takes its host as a parameter — the shape a plugin needs anyway, because pluginkit's host functions only answer inside wasm. The fake host is built from the manifest first and handed to the plugin, so the grants are the manifest's own:
h := plugintest.NewFor(myapp.Manifest(), func(host *plugintest.Host) *pluginkit.Plugin {
return myapp.Plugin(host)
})
func (*Harness) Act ¶
Act is View with an `action` event: a footer button that is not the primary one, or a row action (pass `row_id` in data).
func (*Harness) Do ¶
func (h *Harness) Do(actionID string, params map[string]any, files ...File) (*wire.ActionRunOutput, error)
Do is Run with the parameters a screen would have collected.
func (*Harness) Event ¶
func (h *Harness) Event(event string, files ...File) *wire.ViewEventInput
Event builds a view event on the current selection.
func (*Harness) InLocales ¶
func (h *Harness) InLocales(viewID string, ev *wire.ViewEventInput) (map[string]*wire.Surface, error)
InLocales draws the same screen once per declared language. What comes back is what CheckLocaleParity reads: a string that is empty in one language, or a section that only one language has, is a screen half in the wrong language — the complaint this kit exists for.
func (*Harness) Input ¶
func (h *Harness) Input(actionID string, files ...File) *wire.ActionRunInput
Input builds an ActionRunInput with the manifest's own defaults filled in: the action's output mode, the current selection, the actor, the locale, the non-secret settings and the engine map.
func (*Harness) Languages ¶
Languages is what the manifest promises to speak (["en"] when it says nothing).
func (*Harness) Manifest ¶
Manifest is what describe would answer: the registered manifest with manifest_version filled in.
func (*Harness) OpenInLocales ¶
OpenInLocales is InLocales with an `open` event.
func (*Harness) Page ¶
Page answers a public-page event on a link the plugin opened. The fake host is in share mode: not writable, but `state_set` and `share_state("")` answer for that link, as they do on a real page event.
func (*Harness) Queue ¶
Queue runs the job a surface asked for (`{job: …}`), with that job's params and output override — the second half of a wizard, without the host in between.
func (*Harness) Run ¶
func (h *Harness) Run(actionID string, in *wire.ActionRunInput) (*wire.ActionRunOutput, error)
Run calls the action as filex would: the fake host is in job mode, so outputs, state, locks, engines and shares are allowed.
func (*Harness) Select ¶
Select registers the files a call is made on and answers their refs. Call it once per flow: Open, Submit and Input reuse the selection, so a wizard's three screens do not register the same file three times.
func (*Harness) Tick ¶
Tick runs the wake-up with an input you built yourself — a shorter window, a different clock, settings the administrator has not entered yet.
func (*Harness) UICall ¶ added in v0.48.0
func (h *Harness) UICall(viewID, method string, params any, files ...File) (*wire.UICallOutput, error)
UICall is the app's own interface calling its module (`fx.call(method, params)`): the handler registered in Plugin.UI, in screen mode, with the current selection as the interface's files. The answer is what the interface would receive — the result, or the error it rejects with.
func (*Harness) View ¶
View answers a view event. The fake host is in screen mode: the plugin may read its inputs, but a screen that tries to write a file, take a lock or run an engine is refused exactly as filex refuses it.
func (*Harness) Wake ¶
Wake runs the hourly wake-up as filex would at `now`: the window runs from `now` to the next hourly boundary, the settings and engines are this harness's, and the call is READ-ONLY — a `StateSet` from a tick is refused here exactly as the real host refuses it.
out, err := h.Wake(time.Date(2026, 9, 20, 3, 0, 0, 0, time.UTC)) require.NoError(t, err) require.NoError(t, plugintest.CheckSchedule(h.Manifest(), h.TickInput(now), out))
type Host ¶
type Host struct {
// Recorded traffic, for assertions.
ProgressLog []ProgressLine
Notices []pluginkit.Notice
Mails []Mail
Engines []EngineCall
Requests []pluginkit.HTTPRequest
Logs []string
SettingsGot []string
// EngineFn answers engine_run. The default produces one artefact per
// name in req.Outputs (`engine:<name>` as bytes), or a single
// `out.bin`. Set it to script failures, timeouts and real payloads.
EngineFn func(n int, req pluginkit.EngineRequest) (*pluginkit.EngineResult, error)
// HTTPFn answers http_request for a granted host. The default is a
// 200 with an empty body.
HTTPFn func(req pluginkit.HTTPRequest) (*pluginkit.HTTPResponse, error)
// MailPerHour is the quota mail_send enforces (the real host: 60).
MailPerHour int
// failing — an instance with no signing key.
SignUnavailable string
// SignBudget, when > 0, is how many cert_issue/host_sign calls succeed
// before the host answers `busy` (the real host rate-limits signing).
SignBudget int
// MailConfigured false makes mail_send answer `unavailable`.
MailConfigured bool
// NotifyConfigured false makes notify_send answer `unavailable`.
NotifyConfigured bool
// MaxInputBytes / MaxOutputBytes are the per-file ceilings (0 = none).
MaxInputBytes int64
MaxOutputBytes int64
// BaseURL is the instance a share link points at.
BaseURL string
// Network is what asset_fetch can download: URL → bytes. A URL that is
// not here answers `unavailable` (the server said 404).
Network map[string][]byte
// Offline makes every asset_fetch that needs the network fail with
// `unavailable` — an installation with no internet. The cache still
// answers.
Offline bool
// Downloads lists every URL asset_fetch actually downloaded, in order;
// a call served from the cache adds nothing.
Downloads []string
// contains filtered or unexported fields
}
Host is the in-memory filex. Build one with NewHost, or take the one a Harness made (h.Host).
func NewHost ¶
NewHost builds the fake host for a manifest. The manifest's permissions are the grants: a call the manifest never asked for is refused, so a plugin cannot pass its tests by using a capability it forgot to declare.
func (*Host) Artefact ¶
Artefact registers a file "an engine produced" and answers its ref — what an EngineFn hands back in EngineResult.Outputs.
func (*Host) AssetFetch ¶
AssetFetch is asset_fetch: download url once into the app's cache, check it against the pinned sha256, hand back a ref to read it with. It enforces what the real host does — https, an `http:<host>` grant, no private address, max_bytes within 32 MiB, the hash — and serves a repeat from the cache without touching Network (Downloads does not grow).
func (*Host) Bytes ¶
Bytes answers what a ref holds — an input, an output the plugin wrote or an engine artefact. It is how a test reads the result of a job.
func (*Host) CallSettings ¶
CallSettings is the settings map a call carries: everything the administrator entered EXCEPT the secret fields, which a plugin may only read through `settings_get`.
func (*Host) CertIssue ¶
CertIssue mints a real P-256 certificate from the fake tenant CA (permission `sign`, jobs only), so a signature a test produces actually verifies against the chain.
func (*Host) EngineAvailable ¶
EngineAvailable reports whether the engine is installed AND granted.
func (*Host) EngineRun ¶
func (h *Host) EngineRun(req pluginkit.EngineRequest) (*pluginkit.EngineResult, error)
EngineRun runs one of the host's engines (permission `engines:<name>`, jobs only). Arguments are judged before anything else — including whether the engine exists — so a refused argument is a bug the author sees on every host, not only on the one that happens to have ffmpeg.
func (*Host) EnterJob ¶
func (h *Host) EnterJob()
EnterJob makes the following calls behave like an action job (writable). The Harness does this around Run; call it directly only when driving the plugin's functions yourself.
func (*Host) EnterScreen ¶
func (h *Host) EnterScreen()
EnterScreen makes the following calls behave like a view event: readable, but no outputs, state, locks, engines or shares.
func (*Host) EnterShare ¶
EnterShare makes the following calls behave like a page event on that link: not writable, but state_set and share_state("") answer for it.
func (*Host) FileLockMessage ¶
func (h *Host) FileLockMessage(ref string, ttlDays int, key string, args map[string]string) (time.Time, error)
FileLockMessage is FileLock with a reason named by one of the manifest's `messages` (pluginkit.FileLockMessage). A key the manifest does not declare is refused, as the host refuses it. LockReason reads it back.
func (*Host) FileUnlock ¶
FileUnlock lifts this plugin's lock (no-op when unlocked).
func (*Host) HTTPDo ¶
func (h *Host) HTTPDo(req pluginkit.HTTPRequest) (*pluginkit.HTTPResponse, error)
HTTPDo performs an outbound request (permission `http:<host>`).
func (*Host) HostSign ¶
HostSign signs a sha256 digest with a host-held key. The answer is a DER-encoded ECDSA signature — a real one, verifiable with the leaf.
func (*Host) HostSignInfo ¶
HostSignInfo answers whether this instance can sign (permission `sign`).
func (*Host) InstallEngine ¶
InstallEngine marks an engine as present on this server. Availability and the grant are separate: an engine the manifest never asked for stays refused even when installed.
func (*Host) InstalledEngines ¶
InstalledEngines is the engine map a call carries (ActionRunInput.Engines / CallContext.Engines): installed AND granted, as the host reports it.
func (*Host) KeyDestroy ¶
KeyDestroy discards the private key; the certificate stays.
func (*Host) LockReason ¶
LockReason is the reason a lock on ref was taken with, in every language (FileLockMessage), or nil.
func (*Host) MailSendIn ¶
MailSendIn is MailSend for a mail written in lang (pluginkit.MailSendIn).
func (*Host) NewSigner ¶
func (h *Host) NewSigner(issued *pluginkit.IssuedCert) (*Signer, error)
NewSigner binds an issued certificate to this host.
func (*Host) NotifySend ¶
NotifySend raises a notification (permission `notify:send`).
func (*Host) PlatformSeal ¶
func (h *Host) PlatformSeal() (*pluginkit.IssuedCert, error)
PlatformSeal is the installation's seal for this app: the same key on every call, which KeyDestroy refuses — as on the real host (seal.go).
func (*Host) SetSetting ¶
SetSetting writes one administrator setting (secret fields included).
func (*Host) ShareByToken ¶
ShareByToken answers a link the plugin opened.
func (*Host) ShareCreate ¶
func (h *Host) ShareCreate(req pluginkit.PageCreate) (*pluginkit.PageCreated, error)
ShareCreate opens a public link for an outside participant (permission `public_pages`, jobs only).
func (*Host) ShareRevoke ¶
ShareRevoke ends a link early.
func (*Host) ShareState ¶
ShareState reads a link's durable record into out. Inside a page event token may be "" (the current link).
func (*Host) ShareStateSet ¶
ShareStateSet replaces a link's durable record (≤ 64 KiB).
func (*Host) StateDelete ¶
StateDelete removes one key.
func (*Host) UsersLookup ¶
UsersLookup searches the directory (permission `users:lookup`).
type IssuedKey ¶
type IssuedKey struct {
Ref string
CommonName string
Email string
Cert *x509.Certificate
CertPEM string
Destroyed bool
// contains filtered or unexported fields
}
IssuedKey is a certificate the fake CA minted.
type LangOpts ¶
type LangOpts struct {
// Strict makes warnings fail the test too.
Strict bool
// SameAllowed are strings that are legitimately identical in every
// language — format names ("PNG", "JPEG"), brands, units. Compare
// exactly.
SameAllowed []string
// MinSameLen is the shortest string the "same in two languages" check
// looks at (default 4): "OK", "PDF" and "%" are not translations that
// went missing.
MinSameLen int
}
LangOpts tunes the language checks.
type Mail ¶
type Mail struct {
To string
Subject string
Body string
// Lang is what MailSendIn stated; "" for MailSend.
Lang string
}
Mail is one mail_send call.
type ProgressLine ¶
ProgressLine is one job_progress call.
type Report ¶
type Report []Finding
Report is a list of findings.
func InspectLanguages ¶
InspectLanguages walks every Text of a surface — the title, the toast, the button labels, the field errors and every Text a node carries — and reports the ones that do not speak every declared language.
func InspectLocaleParity ¶
InspectLocaleParity compares the same screen drawn in several languages.
func InspectManifest ¶
InspectManifest reads a manifest the way the host's installer does: the name shape, the closed permission set, unique ids, an action whose view exists, a placement filex can draw, and a settings form that obeys the same field rules as a screen.
func InspectManifestLanguages ¶
InspectManifestLanguages is CheckManifestLanguages' finding list.
func InspectRegistered ¶
InspectRegistered is CheckRegistered's finding list.
func InspectSurface ¶
InspectSurface measures one screen against the renderer's rules:
- every node type is in the catalogue;
- a `select` is a readable choice (it renders as a row of buttons, so its options must be there, labelled and distinct) and `multi` is only on a select;
- at most ONE primary button — a step asks one thing;
- `show_when` / `required_when` name a field of the same form;
- a hidden field's value is not submitted;
- ids and field keys are unique (values arrive flat).
type Share ¶
type Share struct {
Purpose *wire.PagePurpose
Files []wire.OutputRef
}
Share is a public link the plugin opened (share_create).
type Signer ¶
type Signer struct {
Host *Host
KeyRef string
Cert *x509.Certificate
}
Signer is a crypto.Signer over a key the fake host holds, so a PDF library that takes one (pdfsign, pkcs7) is exercised for real.