Module: Plushie::Test::Script

Defined in:
lib/plushie/test/script.rb,
lib/plushie/test/script/runner.rb

Overview

Parser for the .plushie script format.

A .plushie file has a YAML-style header (key: value lines) separated from the instruction body by a line of five or more dashes.

Header keys: app, viewport, theme, backend Instructions: click, type, type_key, press, release, expect, tree_hash, screenshot, assert_text, assert_model, wait, move

Examples:

app Counter
viewport 800x600
theme dark
-----
click "#increment"
click "#increment"
assert_text "#count" "Count: 2"

Defined Under Namespace

Classes: Instruction, ParsedScript, Runner

Class Method Summary collapse

Class Method Details

.parse(source) ⇒ ParsedScript

Parse a .plushie script string into header + instructions.

Parameters:

  • source (String)

    script content

Returns:



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/plushie/test/script.rb', line 35

def parse(source)
  lines = source.lines.map(&:chomp)
  separator_index = lines.index { |l| l.match?(/\A-{5,}\z/) }

  header_lines = separator_index ? lines[0...separator_index] : []
  body_lines = separator_index ? lines[(separator_index + 1)..] : lines

  header = parse_header(header_lines)
  instructions = parse_body(body_lines)

  ParsedScript.new(header: header, instructions: instructions)
end

.parse_body(lines) ⇒ Array<Instruction>

Parse body lines into instruction structs.

Parameters:

  • lines (Array<String>)

Returns:



75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/plushie/test/script.rb', line 75

def parse_body(lines)
  instructions = []
  lines.each do |line|
    line = line.strip
    next if line.empty? || line.start_with?("#")

    tokens = tokenize(line)
    next if tokens.empty?

    command = tokens.shift
    instructions << Instruction.new(command: command, args: tokens)
  end
  instructions
end

.parse_file(path) ⇒ ParsedScript

Parse a .plushie script file.

Parameters:

  • path (String)

    file path

Returns:



52
53
54
# File 'lib/plushie/test/script.rb', line 52

def parse_file(path)
  parse(File.read(path))
end

.parse_header(lines) ⇒ Hash{String => String}

Parse header lines into a hash.

Parameters:

  • lines (Array<String>)

Returns:

  • (Hash{String => String})


60
61
62
63
64
65
66
67
68
69
# File 'lib/plushie/test/script.rb', line 60

def parse_header(lines)
  header = {}
  lines.each do |line|
    line = line.strip
    next if line.empty? || line.start_with?("#")
    key, _, value = line.partition(/\s+/)
    header[key] = value.strip if key && !key.empty?
  end
  header
end

.tokenize(line) ⇒ Array<String>

Tokenize a script line, respecting quoted strings.

Parameters:

  • line (String)

Returns:

  • (Array<String>)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/plushie/test/script.rb', line 94

def tokenize(line)
  tokens = []
  scanner = line.dup
  until scanner.empty?
    scanner.lstrip!
    break if scanner.empty?

    if scanner.start_with?('"')
      # Quoted string
      scanner = scanner[1..]
      end_quote = scanner.index('"')
      if end_quote
        tokens << scanner[0...end_quote]
        scanner = scanner[(end_quote + 1)..]
      else
        # Unterminated quote -- take the rest
        tokens << scanner
        break
      end
    else
      # Unquoted token
      space = scanner.index(/\s/)
      if space
        tokens << scanner[0...space]
        scanner = scanner[space..]
      else
        tokens << scanner
        break
      end
    end
  end
  tokens
end