Skip to content
quarry Artifact [c02b80bbe2]
Login

Artifact [c02b80bbe2]

Artifact c02b80bbe21609e3e06484d0487dd8bf2cb950c2d78dabaf8af6f383b5b8ad22:


package api

import (
	"context"
	"testing"
)

// mentionAccounts is the forge's account list and nothing else: the
// question here is whether a NAME renders as a mention, which never
// needed an index.
type mentionAccounts struct{ names []string }

func (m mentionAccounts) Accounts() ([]Account, error) {
	out := make([]Account, 0, len(m.names))
	for _, n := range m.names {
		out = append(out, Account{Name: n})
	}
	return out, nil
}
func (m mentionAccounts) AddAccount(string, string, bool) error { return nil }
func (m mentionAccounts) SetPassword(string, string) error      { return nil }
func (m mentionAccounts) SetOperator(string, string) error      { return nil }
func (m mentionAccounts) DeleteAccount(string) error            { return nil }
func (m mentionAccounts) Grant(string, string, string) error    { return nil }
func (m mentionAccounts) Revoke(string, string) error           { return nil }
func (m mentionAccounts) GrantsFor(string) (map[string]string, error) {
	return map[string]string{}, nil
}

// An @name rendered as plain text while the SAME @name sends its owner
// a notification is one mention answering two different questions.
//
// dmestas found it in a forum thread: @dmestas told him and rendered as
// prose, because the notify side asks mentionKnown (an account with
// some capability here) and rendering asked the contributor fold (have
// you committed code to this repository). Rendering asks both now.
func TestSomebodyIsMentionableWithoutHavingCommitted(t *testing.T) {
	d := Deps{
		Accounts: mentionAccounts{names: []string{"dmestas", "jva", "stranger"}},
		CapsFor: func(account, repo string) CapSet {
			// Everybody but stranger can see this repository; nobody
			// here has ever committed to it.
			if account == "stranger" {
				return letterCaps("")
			}
			return letterCaps("r")
		},
	}
	// ix is nil on purpose: with no contributor fold to consult, the
	// ONLY thing that can resolve these names is the new predicate.
	r := resolver{repo: "sandbox", scope: &refScope{ctx: context.Background(), d: d}}

	for _, who := range []string{"dmestas", "jva"} {
		url, _, ok := r.ResolveUser(who)
		if !ok {
			t.Errorf("FAIL: @%s renders as plain text but would be notified", who)
		} else {
			t.Logf("ok: @%s resolves to %s", who, url)
		}
	}
	// The gate still holds: a name with no way into this repository is
	// not a mention here, and an unknown name never becomes a dead link.
	for _, who := range []string{"stranger", "nobody"} {
		if _, _, ok := r.ResolveUser(who); ok {
			t.Errorf("FAIL: @%s resolved, and cannot even read this repository", who)
		} else {
			t.Logf("ok: @%s stays plain text", who)
		}
	}
}

// The two rules are ONE rule. A name the notify side would tell is a
// name the renderer must draw, or the reader sees prose where somebody
// was addressed.
func TestRenderingAndNotifyingAgreeOnWhoIsMentionable(t *testing.T) {
	d := Deps{
		Accounts: mentionAccounts{names: []string{"dmestas", "stranger"}},
		CapsFor: func(account, repo string) CapSet {
			if account == "stranger" {
				return letterCaps("")
			}
			return letterCaps("r")
		},
	}
	r := resolver{repo: "sandbox", scope: &refScope{ctx: context.Background(), d: d}}
	text := "cc @dmestas and @stranger in a forum reply"
	told := map[string]bool{}
	for _, who := range mentionsIn(text, d.mentionKnown("sandbox")) {
		told[who] = true
	}
	for _, who := range []string{"dmestas", "stranger"} {
		_, _, drawn := r.ResolveUser(who)
		if drawn != told[who] {
			t.Errorf("FAIL: @%s drawn=%v told=%v — one mention, two answers", who, drawn, told[who])
		} else {
			t.Logf("ok: @%s drawn=%v told=%v", who, drawn, told[who])
		}
	}
}