Browse Source

Implement test helper functions

master
Dylan Baker 5 years ago
parent
commit
497af0aa34
6 changed files with 109 additions and 105 deletions
  1. 1
    1
      package.json
  2. 0
    61
      test/compiler.js
  3. 47
    0
      test/compilerTest.js
  4. 24
    0
      test/helpers.js
  5. 24
    21
      test/lexerTest.js
  6. 13
    22
      test/parserTest.js

+ 1
- 1
package.json View File

4
   "description": "",
4
   "description": "",
5
   "main": "index.js",
5
   "main": "index.js",
6
   "scripts": {
6
   "scripts": {
7
-    "test": "faucet test/*.js",
7
+    "test": "faucet test/*Test.js",
8
     "pretty": "prettier --single-quote --no-semi --trailing-comma all --arrow-parens avoid --write ./**/*.js"
8
     "pretty": "prettier --single-quote --no-semi --trailing-comma all --arrow-parens avoid --write ./**/*.js"
9
   },
9
   },
10
   "keywords": [],
10
   "keywords": [],

+ 0
- 61
test/compiler.js View File

1
-const test = require('tape')
2
-
3
-const Compiler = require('../src/compiler')
4
-const Lexer = require('../src/lexer')
5
-const Parser = require('../src/parser')
6
-const tt = require('../src/tokenTypes')
7
-
8
-test('compiles a simple template', t => {
9
-  t.plan(1)
10
-  const lexer = new Lexer()
11
-  const tokenStream = lexer.scan(`
12
-    (div :class "foobar"
13
-      (p :class "bazquux" "Lorem ipsum dolor sit amet."))
14
-  `)
15
-  const parser = new Parser(tokenStream)
16
-  const tree = parser.parse()
17
-  const compiler = new Compiler(tree)
18
-  const result = compiler.compile()
19
-  t.deepEqual(
20
-    result.replace(/\n/g, '').replace(/  +/g, ''),
21
-    '<div class="foobar"><p class="bazquux">Lorem ipsum dolor sit amet.</p></div>',
22
-  )
23
-})
24
-
25
-test('renders variables according to passed-in context', t => {
26
-  t.plan(1)
27
-  const lexer = new Lexer()
28
-  const tokenStream = lexer.scan(`
29
-    (div :class classOne
30
-      (p :class classTwo bodyText))
31
-  `)
32
-  const parser = new Parser(tokenStream)
33
-  const tree = parser.parse()
34
-  const compiler = new Compiler(tree, {
35
-    classOne: 'foobar',
36
-    classTwo: 'bazquux',
37
-    bodyText: 'Lorem ipsum dolor sit amet.',
38
-  })
39
-  const result = compiler.compile()
40
-  t.deepEqual(
41
-    result.replace(/\n/g, '').replace(/  +/g, ''),
42
-    '<div class="foobar"><p class="bazquux">Lorem ipsum dolor sit amet.</p></div>',
43
-  )
44
-})
45
-
46
-test('self closing tags are respected', function(t) {
47
-  t.plan(1)
48
-  const lexer = new Lexer()
49
-  const tokenStream = lexer.scan(`
50
-    (meta :charset "UTF-8")
51
-    (img :src "test.png")
52
-  `)
53
-  const parser = new Parser(tokenStream)
54
-  const tree = parser.parse()
55
-  const compiler = new Compiler(tree)
56
-  const result = compiler.compile()
57
-  t.deepEqual(
58
-    result.replace(/\n/g, '').replace(/  +/g, ''),
59
-    '<meta charset="UTF-8"><img src="test.png">',
60
-  )
61
-})

+ 47
- 0
test/compilerTest.js View File

1
+const test = require("tape");
2
+const helpers = require("./helpers");
3
+
4
+const tt = require("../src/tokenTypes");
5
+
6
+test("compiles a simple template", t => {
7
+  t.plan(1);
8
+  const result = helpers.compile(`
9
+    (div :class "foobar"
10
+      (p :class "bazquux" "Lorem ipsum dolor sit amet."))
11
+  `);
12
+  t.deepEqual(
13
+    result.replace(/\n/g, "").replace(/  +/g, ""),
14
+    '<div class="foobar"><p class="bazquux">Lorem ipsum dolor sit amet.</p></div>'
15
+  );
16
+});
17
+
18
+test("renders variables according to passed-in context", t => {
19
+  t.plan(1);
20
+  const result = helpers.compile(
21
+    `
22
+      (div :class classOne
23
+        (p :class classTwo bodyText))
24
+    `,
25
+    {
26
+      classOne: "foobar",
27
+      classTwo: "bazquux",
28
+      bodyText: "Lorem ipsum dolor sit amet."
29
+    }
30
+  );
31
+  t.deepEqual(
32
+    result.replace(/\n/g, "").replace(/  +/g, ""),
33
+    '<div class="foobar"><p class="bazquux">Lorem ipsum dolor sit amet.</p></div>'
34
+  );
35
+});
36
+
37
+test("self closing tags are respected", function(t) {
38
+  t.plan(1);
39
+  const result = helpers.compile(`
40
+    (meta :charset "UTF-8")
41
+    (img :src "test.png")
42
+  `);
43
+  t.deepEqual(
44
+    result.replace(/\n/g, "").replace(/  +/g, ""),
45
+    '<meta charset="UTF-8"><img src="test.png">'
46
+  );
47
+});

+ 24
- 0
test/helpers.js View File

1
+const Compiler = require("../src/compiler");
2
+const Lexer = require("../src/lexer");
3
+const Parser = require("../src/parser");
4
+
5
+const scan = source => {
6
+  const lexer = new Lexer();
7
+  return lexer.scan(source);
8
+};
9
+
10
+const parse = source => {
11
+  const parser = new Parser(scan(source));
12
+  return parser.parse();
13
+};
14
+
15
+const compile = (source, context) => {
16
+  const compiler = new Compiler(parse(source), context);
17
+  return compiler.compile();
18
+};
19
+
20
+module.exports = {
21
+  scan: scan,
22
+  parse: parse,
23
+  compile: compile
24
+};

test/lexer.js → test/lexerTest.js View File

1
 const test = require('tape')
1
 const test = require('tape')
2
+const helpers = require('./helpers')
2
 
3
 
3
-const Lexer = require('../src/lexer')
4
 const tt = require('../src/tokenTypes')
4
 const tt = require('../src/tokenTypes')
5
 
5
 
6
 test('lexes simple template correctly', t => {
6
 test('lexes simple template correctly', t => {
7
   t.plan(4)
7
   t.plan(4)
8
-  const lexer = new Lexer()
9
-  let tokens = lexer.scan(
8
+  let tokens = helpers.scan(
10
     '(div :class "foobar" (p "Lorem ipsum dolor sit amet"))',
9
     '(div :class "foobar" (p "Lorem ipsum dolor sit amet"))',
11
   ).tokens
10
   ).tokens
12
   t.deepEqual(tokens.map(token => token.type), [
11
   t.deepEqual(tokens.map(token => token.type), [
32
 
31
 
33
 test('keeps track of line numbers', t => {
32
 test('keeps track of line numbers', t => {
34
   t.plan(2)
33
   t.plan(2)
35
-  const lexer = new Lexer()
36
-  let tokens = lexer.scan(`(
34
+  let tokens = helpers.scan(`(
37
     (div :class "foobar"
35
     (div :class "foobar"
38
       (p :class "bazquux"))
36
       (p :class "bazquux"))
39
   `).tokens
37
   `).tokens
43
 
41
 
44
 test('multiple identifiers in a row are kept separate', t => {
42
 test('multiple identifiers in a row are kept separate', t => {
45
   t.plan(2)
43
   t.plan(2)
46
-  const lexer = new Lexer()
47
-  let tokens = lexer.scan(`(test test test)`).tokens
44
+  let tokens = helpers.scan(`(test test test)`).tokens
48
   t.deepEqual(tokens.map(token => token.type), [
45
   t.deepEqual(tokens.map(token => token.type), [
49
     tt.OPAREN,
46
     tt.OPAREN,
50
     tt.IDENTIFIER,
47
     tt.IDENTIFIER,
53
     tt.CPAREN,
50
     tt.CPAREN,
54
     tt.EOF,
51
     tt.EOF,
55
   ])
52
   ])
56
-  tokens = lexer.scan(`(test "test" test test)`).tokens
53
+  tokens = helpers.scan(`(test "test" test test)`).tokens
57
   t.deepEqual(tokens.map(token => token.type), [
54
   t.deepEqual(tokens.map(token => token.type), [
58
     tt.OPAREN,
55
     tt.OPAREN,
59
     tt.IDENTIFIER,
56
     tt.IDENTIFIER,
69
 
66
 
70
 test('allow special characters inside quotes', t => {
67
 test('allow special characters inside quotes', t => {
71
   t.plan(2)
68
   t.plan(2)
72
-  const lexer = new Lexer()
73
-  let tokens = lexer.scan(`
69
+  let tokens = helpers.scan(`
74
     (p "(test)")
70
     (p "(test)")
75
   `).tokens
71
   `).tokens
76
   t.deepEqual(tokens.map(token => token.type), [
72
   t.deepEqual(tokens.map(token => token.type), [
87
 
83
 
88
 test('lex numbers', t => {
84
 test('lex numbers', t => {
89
   t.plan(2)
85
   t.plan(2)
90
-  const lexer = new Lexer()
91
-  let tokens = lexer.scan('1 2 3 4 5').tokens
86
+  let tokens = helpers.scan('1 2 3 4 5').tokens
92
   t.deepEqual(tokens.map(token => token.type), [
87
   t.deepEqual(tokens.map(token => token.type), [
93
-    tt.NUMBER, tt.NUMBER, tt.NUMBER, tt.NUMBER, tt.NUMBER, tt.EOF,
88
+    tt.NUMBER,
89
+    tt.NUMBER,
90
+    tt.NUMBER,
91
+    tt.NUMBER,
92
+    tt.NUMBER,
93
+    tt.EOF,
94
   ])
94
   ])
95
   t.deepEqual(tokens.map(token => token.value), [
95
   t.deepEqual(tokens.map(token => token.value), [
96
-    1, 2, 3, 4, 5, undefined // undefined is for the EOF
96
+    1,
97
+    2,
98
+    3,
99
+    4,
100
+    5,
101
+    undefined, // undefined is for the EOF
97
   ])
102
   ])
98
 })
103
 })
99
 
104
 
100
 test('lex booleans', t => {
105
 test('lex booleans', t => {
101
   t.plan(2)
106
   t.plan(2)
102
-  const lexer = new Lexer()
103
-  let tokens = lexer.scan('#t #f').tokens
104
-  t.deepEqual(tokens.map(token => token.type), [
105
-    tt.BOOLEAN, tt.BOOLEAN, tt.EOF
106
-  ])
107
+  let tokens = helpers.scan('#t #f').tokens
108
+  t.deepEqual(tokens.map(token => token.type), [tt.BOOLEAN, tt.BOOLEAN, tt.EOF])
107
   t.deepEqual(tokens.map(token => token.value), [
109
   t.deepEqual(tokens.map(token => token.value), [
108
-    true, false, undefined // undefined is for the EOF
110
+    true,
111
+    false,
112
+    undefined, // undefined is for the EOF
109
   ])
113
   ])
110
 })
114
 })
111
-

test/parser.js → test/parserTest.js View File

1
 const test = require('tape')
1
 const test = require('tape')
2
+const helpers = require('./helpers')
2
 
3
 
3
-const Lexer = require('../src/lexer')
4
 const AST = require('../src/ast/index')
4
 const AST = require('../src/ast/index')
5
-const Parser = require('../src/parser')
6
 const tt = require('../src/tokenTypes')
5
 const tt = require('../src/tokenTypes')
7
 
6
 
8
 test('parses token stream into a tree', t => {
7
 test('parses token stream into a tree', t => {
9
   t.plan(1)
8
   t.plan(1)
10
-  const lexer = new Lexer()
11
-  let tokenStream = lexer.scan(`
9
+  const tree = helpers.parse(`
12
     (div :class "foobar"
10
     (div :class "foobar"
13
       (p :class (cond #t "primary" "secondary")))
11
       (p :class (cond #t "primary" "secondary")))
14
   `)
12
   `)
15
-  let parser = new Parser(tokenStream)
16
-  let tree = parser.parse()
17
 
13
 
18
   t.deepEqual(tree, [
14
   t.deepEqual(tree, [
19
     new AST.Application({
15
     new AST.Application({
21
       args: [
17
       args: [
22
         new AST.Attribute({
18
         new AST.Attribute({
23
           name: 'class',
19
           name: 'class',
24
-          value: new AST.String({ value: 'foobar' })
20
+          value: new AST.String({ value: 'foobar' }),
25
         }),
21
         }),
26
         new AST.Application({
22
         new AST.Application({
27
           functionName: new AST.Identifier({ name: 'p' }),
23
           functionName: new AST.Identifier({ name: 'p' }),
34
                   new AST.Boolean({ value: true }),
30
                   new AST.Boolean({ value: true }),
35
                   new AST.String({ value: 'primary' }),
31
                   new AST.String({ value: 'primary' }),
36
                   new AST.String({ value: 'secondary' }),
32
                   new AST.String({ value: 'secondary' }),
37
-                ]
38
-              })
39
-            })
40
-          ]
41
-        })
42
-      ]
43
-    })
33
+                ],
34
+              }),
35
+            }),
36
+          ],
37
+        }),
38
+      ],
39
+    }),
44
   ])
40
   ])
45
 })
41
 })
46
 
42
 
47
 test('allow empty strings', t => {
43
 test('allow empty strings', t => {
48
   t.plan(1)
44
   t.plan(1)
49
-  const lexer = new Lexer()
50
-  const tokenStream = lexer.scan('(p "")')
51
-  const parser = new Parser(tokenStream)
52
-  const tree = parser.parse()
45
+  const tree = helpers.parse('(p "")')
53
 
46
 
54
   t.deepEqual(tree, [
47
   t.deepEqual(tree, [
55
     new AST.Application({
48
     new AST.Application({
56
       functionName: new AST.Identifier({ name: 'p' }),
49
       functionName: new AST.Identifier({ name: 'p' }),
57
-      args: [
58
-        new AST.String({ value: '' })
59
-      ]
60
-    })
50
+      args: [new AST.String({ value: '' })],
51
+    }),
61
   ])
52
   ])
62
 })
53
 })

Loading…
Cancel
Save