valid_title

package
v0.8.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package valid_title ports eslint-plugin-jest's valid-title to Rstest.

The rule body is deliberately independent of the jest implementation rather than shared: almost every step of it is a "report or not" branch, and four of those branches take different values on Rstest (see the D1-D5 comments below). Only the deterministic primitives — regexp compilation, whitespace classification, text ranges — are reused, from internal/utils.

Index

Constants

This section is empty.

Variables

View Source
var ValidTitleRule = rule.Rule{
	Name:   "rstest/valid-title",
	Schema: rule.NewSchema(schemaJSON),
	Run: func(ctx rule.RuleContext, options []any) rule.RuleListeners {
		co := parseCompiledOptions(options)
		if len(co.invalidPatterns) > 0 {
			for _, bad := range co.invalidPatterns {
				ctx.ReportRange(core.NewTextRange(0, 0), rule.RuleMessage{
					Id: "invalidPattern",
					Description: fmt.Sprintf(
						"Invalid regular expression in `%s` option: `%s`: %s",
						bad.optionPath, bad.pattern, bad.err.Error(),
					),
				})
			}
			return rule.RuleListeners{}
		}
		analysis := rstestUtils.GetRstestCallAnalysis(ctx)

		return rule.RuleListeners{
			ast.KindCallExpression: func(node *ast.Node) {

				parsed := analysis.ParseFnCall(node)
				if parsed == nil {
					return
				}
				if parsed.Kind != rstestUtils.RstestFnTypeDescribe && parsed.Kind != rstestUtils.RstestFnTypeTest {
					return
				}

				call := node.AsCallExpression()
				if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
					return
				}
				arg := call.Arguments.Nodes[0]

				title, ok := staticTitle(ctx.SourceFile, arg)
				if !ok {
					if binaryExprContainsStringLit(arg) {
						return
					}
					ignored := false
					if parsed.Kind == rstestUtils.RstestFnTypeDescribe && co.ignoreTypeOfDescribeName {
						ignored = true
					}
					if parsed.Kind == rstestUtils.RstestFnTypeTest && co.ignoreTypeOfTestName {
						ignored = true
					}
					if !ignored && arg.Kind != ast.KindTemplateExpression {
						ctx.ReportNodeWithFixes(arg, rule.RuleMessage{
							Id:          "titleMustBeString",
							Description: "Title must be a string",
						})
					}
					return
				}

				if title == "" {
					ctx.ReportNode(node, rule.RuleMessage{
						Id:          "emptyTitle",
						Description: rstestEmptyFunctionName(parsed.Kind) + " should not have an empty title",
						Data: map[string]string{
							"rstestFunctionName": rstestEmptyFunctionName(parsed.Kind),
						},
					})
					return
				}

				if isArrayParameterizedRegistration(parsed, call) {
					if spec := eachInvalidSpecifier(title); spec != "" {
						ctx.ReportNode(arg, rule.RuleMessage{
							Id:          "invalidEachSpecifier",
							Description: fmt.Sprintf("%q is not a valid format specifier", spec),
							Data:        map[string]string{"specifier": spec},
						})
					}
				}

				if co.disallowedConcat != nil {
					m, err := co.disallowedConcat.Unwrap().FindStringMatch(title)
					if err == nil && m != nil {
						g := m.GroupByNumber(1)
						if g != nil && g.String() != "" {
							word := g.String()
							ctx.ReportNode(arg, rule.RuleMessage{
								Id:          "disallowedWord",
								Description: fmt.Sprintf("%q is not allowed in test titles", word),
								Data:        map[string]string{"word": word},
							})
							return
						}
					}
				}

				if !co.ignoreSpaces {
					trimmed := ecmascript.StringTrim(title)
					if len(trimmed) != len(title) {
						raw := scanner.GetSourceTextOfNodeFromSourceFile(ctx.SourceFile, arg, false)
						fix := accidentalSpaceReplacement(raw)
						if fix == raw {
							ctx.ReportNode(arg, rule.RuleMessage{
								Id:          "accidentalSpace",
								Description: "should not have leading or trailing spaces",
							})
						} else {
							ctx.ReportNodeWithFixes(arg, rule.RuleMessage{
								Id:          "accidentalSpace",
								Description: "should not have leading or trailing spaces",
							}, rule.RuleFixReplace(ctx.SourceFile, arg, fix))
						}
					}
				}

				fnName := parsed.Name
				if parsed.Kind == rstestUtils.RstestFnTypeDescribe {
					fnName = "describe"
				}
				firstTok := title
				if i := strings.IndexByte(title, ' '); i >= 0 {
					firstTok = title[:i]
				}
				if ecmascript.EqualsWhenLowercased(firstTok, fnName) {
					raw := scanner.GetSourceTextOfNodeFromSourceFile(ctx.SourceFile, arg, false)
					msg := rule.RuleMessage{
						Id:          "duplicatePrefix",
						Description: "should not have duplicate prefix",
					}
					if fix, ok := duplicatePrefixReplacement(raw, fnName); ok {
						ctx.ReportNodeWithFixes(arg, msg, rule.RuleFixReplace(ctx.SourceFile, arg, fix))
					} else {
						ctx.ReportNode(arg, msg)
					}
				}

				if me := matcherFor(fnName, co.mustNotMatch); me.re.Test(title) {
					buildMustNotReport(ctx, arg, fnName, me)
					return
				}

				me := matcherFor(fnName, co.mustMatch)
				if me.re != nil && !me.re.TestOrTimeout(title) {
					buildMustMatchReport(ctx, arg, fnName, me)
				}
			},
		}
	},
}

ValidTitleRule enforces rstest/valid-title.

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL