diff --git a/.travis.yml b/.travis.yml
index 2303d5e71..966d2dc08 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,5 @@
language: node_js
-node_js:
- - "8"
- - "6"
+node_js: "lts/*"
jobs:
include:
- stage: test
diff --git a/rollup.config.js b/rollup.config.js
index a91dfecca..86dc2a8b8 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -50,7 +50,7 @@ export default [{
exclude: [ 'test' ],
compilerOptions: {
module: 'ES2015',
- paths: { 'template': ['src/parser/template-browser'] }
+ paths: { 'src/fs': ['src/fs/browser'] }
}
}
})
@@ -71,7 +71,7 @@ export default [{
exclude: [ 'test' ],
compilerOptions: {
module: 'ES2015',
- paths: { 'template': ['src/parser/template-browser'] }
+ paths: { 'src/fs': ['src/fs/browser'] }
}
}
}),
diff --git a/src/builtin/filters/index.ts b/src/builtin/filters/index.ts
index e47aa10d8..c3bdc588a 100644
--- a/src/builtin/filters/index.ts
+++ b/src/builtin/filters/index.ts
@@ -1,4 +1,3 @@
-import { assign } from 'src/util/underscore'
import html from './html'
import str from './string'
import math from './math'
@@ -7,6 +6,4 @@ import array from './array'
import date from './date'
import obj from './object'
-const filters = assign({}, html, str, math, url, date, obj, array)
-
-export default filters
+export default { ...html, ...str, ...math, ...url, ...date, ...obj, ...array }
diff --git a/src/builtin/tags/include.ts b/src/builtin/tags/include.ts
index 45d4f6298..615d65d84 100644
--- a/src/builtin/tags/include.ts
+++ b/src/builtin/tags/include.ts
@@ -45,7 +45,7 @@ export default {
if (this.with) {
hash[filepath] = evalValue(this.with, scope)
}
- const templates = await this.liquid.getTemplate(filepath, scope.opts.root)
+ const templates = await this.liquid.getTemplate(filepath, scope.opts)
scope.push(hash)
const html = await this.liquid.renderer.renderTemplates(templates, scope)
scope.pop(hash)
diff --git a/src/builtin/tags/layout.ts b/src/builtin/tags/layout.ts
index 8fb229acf..69942e102 100644
--- a/src/builtin/tags/layout.ts
+++ b/src/builtin/tags/layout.ts
@@ -31,7 +31,7 @@ export default {
if (scope.blocks[''] === undefined) {
scope.blocks[''] = html
}
- const templates = await this.liquid.getTemplate(layout, scope.opts.root)
+ const templates = await this.liquid.getTemplate(layout, scope.opts)
scope.push(hash)
scope.blockMode = BlockMode.OUTPUT
const partial = await this.liquid.renderer.renderTemplates(templates, scope)
diff --git a/src/parser/template-browser.ts b/src/fs/browser.ts
similarity index 69%
rename from src/parser/template-browser.ts
rename to src/fs/browser.ts
index 37aa91eb8..50356b34f 100644
--- a/src/parser/template-browser.ts
+++ b/src/fs/browser.ts
@@ -1,4 +1,5 @@
-import { last, isArray } from '../util/underscore'
+import { last } from '../util/underscore'
+import IFS from './ifs'
function domResolve (root, path) {
const base = document.createElement('base')
@@ -15,25 +16,17 @@ function domResolve (root, path) {
return resolved
}
-export function resolve (filepath, root, options) {
- root = root || options.root
- if (isArray(root)) {
- root = root[0]
- }
- if (root.length && last(root) !== '/') {
- root += '/'
- }
+function resolve (root, filepath, ext) {
+ if (root.length && last(root) !== '/') root += '/'
const url = domResolve(root, filepath)
return url.replace(/^(\w+:\/\/[^/]+)(\/[^?]+)/, (str, origin, path) => {
const last = path.split('/').pop()
- if (/\.\w+$/.test(last)) {
- return str
- }
- return origin + path + options.extname
+ if (/\.\w+$/.test(last)) return str
+ return origin + path + ext
})
}
-export async function read (url: string): Promise {
+async function readFile (url: string): Promise {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onload = () => {
@@ -50,3 +43,9 @@ export async function read (url: string): Promise {
xhr.send()
})
}
+
+async function exists () {
+ return true
+}
+
+export default { readFile, resolve, exists } as IFS
diff --git a/src/fs/ifs.ts b/src/fs/ifs.ts
new file mode 100644
index 000000000..637a0e7c4
--- /dev/null
+++ b/src/fs/ifs.ts
@@ -0,0 +1,5 @@
+export default interface IFS {
+ exists: (filepath?: string) => Promise
+ readFile: (filepath:string) => Promise
+ resolve: (root: string, file: string, ext: string) => string
+}
diff --git a/src/fs/node.ts b/src/fs/node.ts
new file mode 100644
index 000000000..7ee93c966
--- /dev/null
+++ b/src/fs/node.ts
@@ -0,0 +1,22 @@
+import * as _ from '../util/underscore'
+import { resolve, extname } from 'path'
+import { stat, readFile } from 'fs'
+import IFS from './ifs'
+
+const statAsync = _.promisify(stat) as (filepath: string) => Promise
p >" | strip_html }}', '')
+ })
+ })
+})
diff --git a/test/unit/builtin/filters/math.ts b/test/unit/builtin/filters/math.ts
new file mode 100644
index 000000000..942302e67
--- /dev/null
+++ b/test/unit/builtin/filters/math.ts
@@ -0,0 +1,64 @@
+import { test, ctx, liquid } from 'test/stub/render'
+
+describe('filters/math', function () {
+ describe('abs', function () {
+ it('should return 3 for -3', () => test('{{ -3 | abs }}', '3'))
+ it('should return 2 for arr[0]', () => test('{{ arr[0] | abs }}', '2'))
+ it('should return convert string', () => test('{{ "-3" | abs }}', '3'))
+ })
+ describe('ceil', function () {
+ it('should return "2" for 1.2', () => test('{{ 1.2 | ceil }}', '2'))
+ it('should return "2" for 2.0', () => test('{{ 2.0 | ceil }}', '2'))
+ it('should return "4" for 3.5', () => test('{{ "3.5" | ceil }}', '4'))
+ it('should return "184" for 183.357', () => test('{{ 183.357 | ceil }}', '184'))
+ })
+ describe('divided_by', function () {
+ it('should return 2 for 4,2', () => test('{{4 | divided_by: 2}}', '2'))
+ it('should return 4 for 16,4', () => test('{{16 | divided_by: 4}}', '4'))
+ it('should return 1 for 5,3', () => test('{{5 | divided_by: 3}}', (5 / 3).toString()))
+ it('should convert string to number', () => test('{{"6" | divided_by: "3"}}', '2'))
+ })
+ describe('floor', function () {
+ it('should return "1" for 1.2', () => test('{{ 1.2 | floor }}', '1'))
+ it('should return "2" for 2.0', () => test('{{ 2.0 | floor }}', '2'))
+ it('should return "183" for 183.357', () => test('{{ 183.357 | floor }}', '183'))
+ it('should return "3" for 3.5', () => test('{{ "3.5" | floor }}', '3'))
+ })
+ describe('minus', function () {
+ it('should return "2" for 4,2', () => test('{{ 4 | minus: 2 }}', '2'))
+ it('should return "12" for 16,4', () => test('{{ 16 | minus: 4 }}', '12'))
+ it('should return "171.357" for 183.357,12',
+ () => test('{{ 183.357 | minus: 12 }}', '171.357'))
+ it('should convert first arg as number', () => test('{{ "4" | minus: 1 }}', '3'))
+ it('should convert both args as number', () => test('{{ "4" | minus: "1" }}', '3'))
+ })
+ describe('modulo', function () {
+ it('should return "1" for 3,2', () => test('{{ 3 | modulo: 2 }}', '1'))
+ it('should return "3" for 24,7', () => test('{{ 24 | modulo: 7 }}', '3'))
+ it('should return "3.357" for 183.357,12',
+ () => test('{{ 183.357 | modulo: 12 }}', '3.357'))
+ it('should convert string', () => test('{{ "24" | modulo: "7" }}', '3'))
+ })
+ describe('plus', function () {
+ it('should return "6" for 4,2', () => test('{{ 4 | plus: 2 }}', '6'))
+ it('should return "20" for 16,4', () => test('{{ 16 | plus: 4 }}', '20'))
+ it('should return "195.357" for 183.357,12',
+ () => test('{{ 183.357 | plus: 12 }}', '195.357'))
+ it('should convert first arg as number', () => test('{{ "4" | plus: 2 }}', '6'))
+ it('should convert both args as number', () => test('{{ "4" | plus: "2" }}', '6'))
+ })
+ describe('round', function () {
+ it('should return "1" for 1.2', () => test('{{1.2|round}}', '1'))
+ it('should return "3" for 2.7', () => test('{{2.7|round}}', '3'))
+ it('should return "183.36" for 183.357,2',
+ () => test('{{183.357|round: 2}}', '183.36'))
+ it('should convert string to number', () => test('{{"2.7"|round}}', '3'))
+ })
+ describe('times', function () {
+ it('should return "6" for 3,2', () => test('{{ 3 | times: 2 }}', '6'))
+ it('should return "168" for 24,7', () => test('{{ 24 | times: 7 }}', '168'))
+ it('should return "2200.284" for 183.357,12',
+ () => test('{{ 183.357 | times: 12 }}', '2200.284'))
+ it('should convert string to number', () => test('{{ "24" | times: "7" }}', '168'))
+ })
+})
diff --git a/test/unit/builtin/filters/object.ts b/test/unit/builtin/filters/object.ts
new file mode 100644
index 000000000..671edf27f
--- /dev/null
+++ b/test/unit/builtin/filters/object.ts
@@ -0,0 +1,8 @@
+import { test, ctx, liquid } from 'test/stub/render'
+
+describe('filters/object', function () {
+ describe('default', function () {
+ it('should use default when falsy', () => test('{{false |default: "a"}}', 'a'))
+ it('should not use default when truthy', () => test('{{true |default: "a"}}', 'true'))
+ })
+})
diff --git a/test/unit/builtin/filters/string.ts b/test/unit/builtin/filters/string.ts
new file mode 100644
index 000000000..c8baf3435
--- /dev/null
+++ b/test/unit/builtin/filters/string.ts
@@ -0,0 +1,161 @@
+import { test, ctx, liquid } from 'test/stub/render'
+
+describe('filters/string', function () {
+ describe('append', function () {
+ it('should return "-3abc" for -3, "abc"',
+ () => test('{{ -3 | append: "abc" }}', '-3abc'))
+ it('should return "abar" for "a",foo', () => test('{{ "a" | append: foo }}', 'abar'))
+ })
+ describe('capitalize', function () {
+ it('should capitalize first', () => test('{{ "i am good" | capitalize }}', 'I am good'))
+ })
+ describe('concat', function () {
+ it('should concat arrays', () => test(`
+ {%- assign fruits = "apples, oranges, peaches" | split: ", " -%}
+ {%- assign vegetables = "carrots, turnips, potatoes" | split: ", " -%}
+
+ {%- assign everything = fruits | concat: vegetables -%}
+
+ {%- for item in everything -%}
+ - {{ item }}
+ {% endfor -%}`, `- apples
+ - oranges
+ - peaches
+ - carrots
+ - turnips
+ - potatoes
+ `))
+ it('should support chained concat', () => test(`
+ {%- assign fruits = "apples, oranges, peaches" | split: ", " -%}
+ {%- assign vegetables = "carrots, turnips, potatoes" | split: ", " -%}
+ {%- assign furniture = "chairs, tables, shelves" | split: ", " -%}
+ {%- assign everything = fruits | concat: vegetables | concat: furniture -%}
+
+ {%- for item in everything -%}
+ - {{ item }}
+ {% endfor -%}`, `- apples
+ - oranges
+ - peaches
+ - carrots
+ - turnips
+ - potatoes
+ - chairs
+ - tables
+ - shelves
+ `))
+ })
+ describe('downcase', function () {
+ it('should return "parker moore" for "Parker Moore"',
+ () => test('{{ "Parker Moore" | downcase }}', 'parker moore'))
+ it('should return "apple" for "apple"',
+ () => test('{{ "apple" | downcase }}', 'apple'))
+ })
+ describe('split', function () {
+ it('should support split/first', function () {
+ const src = '{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}' +
+ '{{ my_array | first }}'
+ return test(src, 'apples')
+ })
+ })
+ it('should support upcase', () => test('{{ "Parker Moore" | upcase }}', 'PARKER MOORE'))
+ it('should support lstrip', function () {
+ const src = '{{ " So much room for activities! " | lstrip }}'
+ return test(src, 'So much room for activities! ')
+ })
+ it('should support string_with_newlines', function () {
+ const src = '{% capture string_with_newlines %}\n' +
+ 'Hello\n' +
+ 'there\n' +
+ '{% endcapture %}' +
+ '{{ string_with_newlines | newline_to_br }}'
+ const dst = '
' +
+ 'Hello
' +
+ 'there
'
+ return test(src, dst)
+ })
+ it('should support prepend', function () {
+ return test('{% assign url = "liquidmarkup.com" %}' +
+ '{{ "/index.html" | prepend: url }}',
+ 'liquidmarkup.com/index.html')
+ })
+ it('should support remove', function () {
+ return test('{{ "I strained to see the train through the rain" | remove: "rain" }}',
+ 'I sted to see the t through the ')
+ })
+ it('should support remove_first', function () {
+ return test('{{ "I strained to see the train through the rain" | remove_first: "rain" }}',
+ 'I sted to see the train through the rain')
+ })
+ it('should support replace', function () {
+ return test('{{ "Take my protein pills and put my helmet on" | replace: "my", "your" }}',
+ 'Take your protein pills and put your helmet on')
+ })
+ it('should support replace_first', function () {
+ return test('{% assign my_string = "Take my protein pills and put my helmet on" %}\n' +
+ '{{ my_string | replace_first: "my", "your" }}',
+ '\nTake your protein pills and put my helmet on')
+ })
+ it('should support rstrip', function () {
+ return test('{{ " So much room for activities! " | rstrip }}',
+ ' So much room for activities!')
+ })
+ it('should support split', function () {
+ return test('{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
+ '{% for member in beatles %}' +
+ '{{ member }} ' +
+ '{% endfor %}',
+ 'John Paul George Ringo ')
+ })
+ it('should support strip', function () {
+ return test('{{ " So much room for activities! " | strip }}',
+ 'So much room for activities!')
+ })
+ it('should support strip_newlines', function () {
+ return test('{% capture string_with_newlines %}\n' +
+ 'Hello\nthere\n{% endcapture %}' +
+ '{{ string_with_newlines | strip_newlines }}',
+ 'Hellothere')
+ })
+ describe('truncate', function () {
+ it('should truncate when string too long', function () {
+ return test('{{ "Ground control to Major Tom." | truncate: 20 }}',
+ 'Ground control to...')
+ })
+ it('should not truncate when string not long enough', function () {
+ return test('{{ "Ground control to Major Tom." | truncate: 80 }}',
+ 'Ground control to Major Tom.')
+ })
+ it('should truncate with custom ellipsis', function () {
+ return test('{{ "Ground control to Major Tom." | truncate: 25,", and so on" }}',
+ 'Ground control, and so on')
+ })
+ it('should truncate with empty custom ellipsis', function () {
+ return test('{{ "Ground control to Major Tom." | truncate: 20, "" }}',
+ 'Ground control to Ma')
+ })
+ it('should not truncate when short enough', function () {
+ return test('{{ "12345" | truncate: 5 }}', '12345')
+ })
+ it('should default to 16', function () {
+ return test('{{ "1234567890abcdefghi" | truncate }}', '1234567890abc...')
+ })
+ })
+ describe('truncatewords', function () {
+ it('should truncate when too many words', function () {
+ return test('{{ "Ground control to Major Tom." | truncatewords: 3 }}',
+ 'Ground control to...')
+ })
+ it('should not truncate when not enough words', function () {
+ return test('{{ "Ground control to Major Tom." | truncatewords: 8 }}',
+ 'Ground control to Major Tom.')
+ })
+ it('should truncate with custom ellipsis', function () {
+ return test('{{ "Ground control to Major Tom." | truncatewords: 3, "--" }}',
+ 'Ground control to--')
+ })
+ it('should truncate with empty custom ellipsis', function () {
+ return test('{{ "Ground control to Major Tom." | truncatewords: 3, "" }}',
+ 'Ground control to')
+ })
+ })
+})
diff --git a/test/unit/builtin/filters/url.ts b/test/unit/builtin/filters/url.ts
new file mode 100644
index 000000000..1c791c8db
--- /dev/null
+++ b/test/unit/builtin/filters/url.ts
@@ -0,0 +1,15 @@
+import { test, ctx, liquid } from 'test/stub/render'
+
+describe('filters/url', function () {
+ describe('url_decode', function () {
+ it('should decode %xx and +',
+ () => test('{{ "%27Stop%21%27+said+Fred" | url_decode }}', "'Stop!' said Fred"))
+ })
+
+ describe('url_encode', function () {
+ it('should encode @',
+ () => test('{{ "john@liquid.com" | url_encode }}', 'john%40liquid.com'))
+ it('should encode ',
+ () => test('{{ "Tetsuro Takara" | url_encode }}', 'Tetsuro+Takara'))
+ })
+})
diff --git a/test/unit/tags/assign.ts b/test/unit/builtin/tags/assign.ts
similarity index 100%
rename from test/unit/tags/assign.ts
rename to test/unit/builtin/tags/assign.ts
diff --git a/test/unit/tags/capture.ts b/test/unit/builtin/tags/capture.ts
similarity index 100%
rename from test/unit/tags/capture.ts
rename to test/unit/builtin/tags/capture.ts
diff --git a/test/unit/tags/case.ts b/test/unit/builtin/tags/case.ts
similarity index 100%
rename from test/unit/tags/case.ts
rename to test/unit/builtin/tags/case.ts
diff --git a/test/unit/tags/comment.ts b/test/unit/builtin/tags/comment.ts
similarity index 100%
rename from test/unit/tags/comment.ts
rename to test/unit/builtin/tags/comment.ts
diff --git a/test/unit/tags/cycle.ts b/test/unit/builtin/tags/cycle.ts
similarity index 100%
rename from test/unit/tags/cycle.ts
rename to test/unit/builtin/tags/cycle.ts
diff --git a/test/unit/tags/decrement.ts b/test/unit/builtin/tags/decrement.ts
similarity index 100%
rename from test/unit/tags/decrement.ts
rename to test/unit/builtin/tags/decrement.ts
diff --git a/test/unit/tags/for.ts b/test/unit/builtin/tags/for.ts
similarity index 100%
rename from test/unit/tags/for.ts
rename to test/unit/builtin/tags/for.ts
diff --git a/test/unit/tags/if.ts b/test/unit/builtin/tags/if.ts
similarity index 100%
rename from test/unit/tags/if.ts
rename to test/unit/builtin/tags/if.ts
diff --git a/test/unit/tags/include.ts b/test/unit/builtin/tags/include.ts
similarity index 100%
rename from test/unit/tags/include.ts
rename to test/unit/builtin/tags/include.ts
diff --git a/test/unit/tags/increment.ts b/test/unit/builtin/tags/increment.ts
similarity index 100%
rename from test/unit/tags/increment.ts
rename to test/unit/builtin/tags/increment.ts
diff --git a/test/unit/tags/layout.ts b/test/unit/builtin/tags/layout.ts
similarity index 100%
rename from test/unit/tags/layout.ts
rename to test/unit/builtin/tags/layout.ts
diff --git a/test/unit/tags/raw.ts b/test/unit/builtin/tags/raw.ts
similarity index 100%
rename from test/unit/tags/raw.ts
rename to test/unit/builtin/tags/raw.ts
diff --git a/test/unit/tags/tablerow.ts b/test/unit/builtin/tags/tablerow.ts
similarity index 100%
rename from test/unit/tags/tablerow.ts
rename to test/unit/builtin/tags/tablerow.ts
diff --git a/test/unit/tags/unless.ts b/test/unit/builtin/tags/unless.ts
similarity index 100%
rename from test/unit/tags/unless.ts
rename to test/unit/builtin/tags/unless.ts
diff --git a/test/unit/filters.ts b/test/unit/filters.ts
deleted file mode 100644
index daedd8cb5..000000000
--- a/test/unit/filters.ts
+++ /dev/null
@@ -1,425 +0,0 @@
-import { expect } from 'chai'
-import Liquid from '../../src/liquid'
-
-const ctx = {
- date: new Date(),
- foo: 'bar',
- arr: [-2, 'a'],
- obj: {
- foo: 'bar'
- },
- func: function () {},
- posts: [{
- category: 'foo'
- }, {
- category: 'bar'
- }]
-}
-let liquid
-
-async function test (src, dst) {
- const html = await liquid.parseAndRender(src, ctx)
- return expect(html).to.equal(dst)
-}
-
-describe('filters', function () {
- before(() => { liquid = new Liquid() })
- describe('abs', function () {
- it('should return 3 for -3', () => test('{{ -3 | abs }}', '3'))
- it('should return 2 for arr[0]', () => test('{{ arr[0] | abs }}', '2'))
- it('should return convert string', () => test('{{ "-3" | abs }}', '3'))
- })
-
- describe('append', function () {
- it('should return "-3abc" for -3, "abc"',
- () => test('{{ -3 | append: "abc" }}', '-3abc'))
- it('should return "abar" for "a",foo', () => test('{{ "a" | append: foo }}', 'abar'))
- })
-
- it('should support capitalize', () => test('{{ "i am good" | capitalize }}', 'I am good'))
-
- describe('ceil', function () {
- it('should return "2" for 1.2', () => test('{{ 1.2 | ceil }}', '2'))
- it('should return "2" for 2.0', () => test('{{ 2.0 | ceil }}', '2'))
- it('should return "4" for 3.5', () => test('{{ "3.5" | ceil }}', '4'))
- it('should return "184" for 183.357', () => test('{{ 183.357 | ceil }}', '184'))
- })
-
- describe('concat', function () {
- it('should concat arrays', () => test(`
- {%- assign fruits = "apples, oranges, peaches" | split: ", " -%}
- {%- assign vegetables = "carrots, turnips, potatoes" | split: ", " -%}
-
- {%- assign everything = fruits | concat: vegetables -%}
-
- {%- for item in everything -%}
- - {{ item }}
- {% endfor -%}`, `- apples
- - oranges
- - peaches
- - carrots
- - turnips
- - potatoes
- `))
- it('should support chained concat', () => test(`
- {%- assign fruits = "apples, oranges, peaches" | split: ", " -%}
- {%- assign vegetables = "carrots, turnips, potatoes" | split: ", " -%}
- {%- assign furniture = "chairs, tables, shelves" | split: ", " -%}
- {%- assign everything = fruits | concat: vegetables | concat: furniture -%}
-
- {%- for item in everything -%}
- - {{ item }}
- {% endfor -%}`, `- apples
- - oranges
- - peaches
- - carrots
- - turnips
- - potatoes
- - chairs
- - tables
- - shelves
- `))
- })
-
- describe('date', function () {
- it('should support date: %a %b %d %Y', function () {
- const str = ctx.date.toDateString()
- return test('{{ date | date:"%a %b %d %Y"}}', str)
- })
- it('should create a new Date when given "now"', function () {
- return test('{{ "now" | date: "%Y"}}', (new Date()).getFullYear().toString())
- })
- it('should parse as Date when given UTC string', function () {
- return test('{{ "1991-02-22T00:00:00" | date: "%Y"}}', '1991')
- })
- it('should render string as string if not valid', function () {
- return test('{{ "foo" | date: "%Y"}}', 'foo')
- })
- it('should render object as string if not valid', function () {
- return test('{{ obj | date: "%Y"}}', '{"foo":"bar"}')
- })
- })
-
- describe('default', function () {
- it('should use default when falsy', () => test('{{false |default: "a"}}', 'a'))
- it('should not use default when truthy', () => test('{{true |default: "a"}}', 'true'))
- })
-
- describe('divided_by', function () {
- it('should return 2 for 4,2', () => test('{{4 | divided_by: 2}}', '2'))
- it('should return 4 for 16,4', () => test('{{16 | divided_by: 4}}', '4'))
- it('should return 1 for 5,3', () => test('{{5 | divided_by: 3}}', (5 / 3).toString()))
- it('should convert string to number', () => test('{{"6" | divided_by: "3"}}', '2'))
- })
-
- describe('downcase', function () {
- it('should return "parker moore" for "Parker Moore"',
- () => test('{{ "Parker Moore" | downcase }}', 'parker moore'))
- it('should return "apple" for "apple"',
- () => test('{{ "apple" | downcase }}', 'apple'))
- })
-
- describe('escape', function () {
- it('should escape \' and &', function () {
- return test('{{ "Have you read \'James & the Giant Peach\'?" | escape }}',
- 'Have you read 'James & the Giant Peach'?')
- })
- it('should escape normal string', function () {
- return test('{{ "Tetsuro Takara" | escape }}', 'Tetsuro Takara')
- })
- it('should escape function', function () {
- return test('{{ func | escape }}', 'function () { }')
- })
- })
-
- describe('escape_once', function () {
- it('should do escape', () =>
- test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'))
- it('should not escape twice',
- () => test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'))
- })
-
- it('should support split/first', function () {
- const src = '{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}' +
- '{{ my_array | first }}'
- return test(src, 'apples')
- })
-
- describe('floor', function () {
- it('should return "1" for 1.2', () => test('{{ 1.2 | floor }}', '1'))
- it('should return "2" for 2.0', () => test('{{ 2.0 | floor }}', '2'))
- it('should return "183" for 183.357', () => test('{{ 183.357 | floor }}', '183'))
- it('should return "3" for 3.5', () => test('{{ "3.5" | floor }}', '3'))
- })
-
- describe('join', function () {
- it('should support join', function () {
- const src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
- '{{ beatles | join: " and " }}'
- return test(src, 'John and Paul and George and Ringo')
- })
- it('should default separator to space', function () {
- const src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
- '{{ beatles | join }}'
- return test(src, 'John Paul George Ringo')
- })
- })
-
- it('should support split/last', function () {
- const src = '{% assign my_array = "zebra, octopus, giraffe, tiger" | split: ", " %}' +
- '{{ my_array|last }}'
- return test(src, 'tiger')
- })
-
- it('should support lstrip', function () {
- const src = '{{ " So much room for activities! " | lstrip }}'
- return test(src, 'So much room for activities! ')
- })
-
- it('should support map', function () {
- return test('{{posts | map: "category"}}', '["foo","bar"]')
- })
-
- describe('minus', function () {
- it('should return "2" for 4,2', () => test('{{ 4 | minus: 2 }}', '2'))
- it('should return "12" for 16,4', () => test('{{ 16 | minus: 4 }}', '12'))
- it('should return "171.357" for 183.357,12',
- () => test('{{ 183.357 | minus: 12 }}', '171.357'))
- it('should convert first arg as number', () => test('{{ "4" | minus: 1 }}', '3'))
- it('should convert both args as number', () => test('{{ "4" | minus: "1" }}', '3'))
- })
-
- describe('modulo', function () {
- it('should return "1" for 3,2', () => test('{{ 3 | modulo: 2 }}', '1'))
- it('should return "3" for 24,7', () => test('{{ 24 | modulo: 7 }}', '3'))
- it('should return "3.357" for 183.357,12',
- () => test('{{ 183.357 | modulo: 12 }}', '3.357'))
- it('should convert string', () => test('{{ "24" | modulo: "7" }}', '3'))
- })
-
- it('should support string_with_newlines', function () {
- const src = '{% capture string_with_newlines %}\n' +
- 'Hello\n' +
- 'there\n' +
- '{% endcapture %}' +
- '{{ string_with_newlines | newline_to_br }}'
- const dst = '
' +
- 'Hello
' +
- 'there
'
- return test(src, dst)
- })
-
- describe('plus', function () {
- it('should return "6" for 4,2', () => test('{{ 4 | plus: 2 }}', '6'))
- it('should return "20" for 16,4', () => test('{{ 16 | plus: 4 }}', '20'))
- it('should return "195.357" for 183.357,12',
- () => test('{{ 183.357 | plus: 12 }}', '195.357'))
- it('should convert first arg as number', () => test('{{ "4" | plus: 2 }}', '6'))
- it('should convert both args as number', () => test('{{ "4" | plus: "2" }}', '6'))
- })
-
- it('should support prepend', function () {
- return test('{% assign url = "liquidmarkup.com" %}' +
- '{{ "/index.html" | prepend: url }}',
- 'liquidmarkup.com/index.html')
- })
-
- it('should support remove', function () {
- return test('{{ "I strained to see the train through the rain" | remove: "rain" }}',
- 'I sted to see the t through the ')
- })
-
- it('should support remove_first', function () {
- return test('{{ "I strained to see the train through the rain" | remove_first: "rain" }}',
- 'I sted to see the train through the rain')
- })
-
- it('should support replace', function () {
- return test('{{ "Take my protein pills and put my helmet on" | replace: "my", "your" }}',
- 'Take your protein pills and put your helmet on')
- })
-
- it('should support replace_first', function () {
- return test('{% assign my_string = "Take my protein pills and put my helmet on" %}\n' +
- '{{ my_string | replace_first: "my", "your" }}',
- '\nTake your protein pills and put my helmet on')
- })
-
- it('should support reverse', function () {
- return test('{{ "Ground control to Major Tom." | split: "" | reverse | join: "" }}',
- '.moT rojaM ot lortnoc dnuorG')
- })
-
- describe('round', function () {
- it('should return "1" for 1.2', () => test('{{1.2|round}}', '1'))
- it('should return "3" for 2.7', () => test('{{2.7|round}}', '3'))
- it('should return "183.36" for 183.357,2',
- () => test('{{183.357|round: 2}}', '183.36'))
- it('should convert string to number', () => test('{{"2.7"|round}}', '3'))
- })
-
- it('should support rstrip', function () {
- return test('{{ " So much room for activities! " | rstrip }}',
- ' So much room for activities!')
- })
-
- describe('size', function () {
- it('should return string length',
- () => test('{{ "Ground control to Major Tom." | size }}', '28'))
- it('should return array size', function () {
- return test('{% assign my_array = "apples, oranges, peaches, plums"' +
- ' | split: ", " %}{{ my_array | size }}',
- '4')
- })
- it('should also be used with dot notation - string',
- () => test('{% assign my_string = "Ground control to Major Tom." %}{{ my_string.size }}', '28'))
- it('should also be used with dot notation - array',
- () => test('{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}{{ my_array.size }}', '4'))
- })
-
- describe('slice', function () {
- it('should slice first char by 0', () => test('{{ "Liquid" | slice: 0 }}', 'L'))
- it('should slice third char by 2', () => test('{{ "Liquid" | slice: 2 }}', 'q'))
- it('should slice substr by 2,5', () => test('{{ "Liquid" | slice: 2, 5 }}', 'quid'))
- it('should slice substr by -3,2', () => test('{{ "Liquid" | slice: -3, 2 }}', 'ui'))
- it('should support array', () => test('{{ "1,2,3,4" | split: "," | slice: 1,2 | join }}', '2 3'))
- })
-
- it('should support sort', function () {
- return test('{% assign my_array = "zebra, octopus, giraffe, Sally Snake"' +
- ' | split: ", " %}' +
- '{{ my_array | sort | join: ", " }}',
- 'Sally Snake, giraffe, octopus, zebra')
- })
-
- it('should support split', function () {
- return test('{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
- '{% for member in beatles %}' +
- '{{ member }} ' +
- '{% endfor %}',
- 'John Paul George Ringo ')
- })
-
- it('should support strip', function () {
- return test('{{ " So much room for activities! " | strip }}',
- 'So much room for activities!')
- })
-
- describe('strip_html', function () {
- it('should strip all tags', function () {
- return test('{{ "Have you read Ulysses?" | strip_html }}',
- 'Have you read Ulysses?')
- })
- it('should strip all comment tags', function () {
- return test('{{ "Ulysses?" | strip_html }}',
- 'Ulysses?')
- })
- it('should strip all style tags and their contents', function () {
- return test('{{ "Ulysses?" | strip_html }}',
- 'Ulysses?')
- })
- it('should strip all scripts tags and their contents', function () {
- return test('{{ "Ulysses?" | strip_html }}',
- 'Ulysses?')
- })
- it('should strip until empty', function () {
- return test('{{"
< p > p >" | strip_html }}', '')
- })
- })
-
- it('should support strip_newlines', function () {
- return test('{% capture string_with_newlines %}\n' +
- 'Hello\nthere\n{% endcapture %}' +
- '{{ string_with_newlines | strip_newlines }}',
- 'Hellothere')
- })
-
- describe('times', function () {
- it('should return "6" for 3,2', () => test('{{ 3 | times: 2 }}', '6'))
- it('should return "168" for 24,7', () => test('{{ 24 | times: 7 }}', '168'))
- it('should return "2200.284" for 183.357,12',
- () => test('{{ 183.357 | times: 12 }}', '2200.284'))
- it('should convert string to number', () => test('{{ "24" | times: "7" }}', '168'))
- })
-
- describe('truncate', function () {
- it('should truncate when string too long', function () {
- return test('{{ "Ground control to Major Tom." | truncate: 20 }}',
- 'Ground control to...')
- })
- it('should not truncate when string not long enough', function () {
- return test('{{ "Ground control to Major Tom." | truncate: 80 }}',
- 'Ground control to Major Tom.')
- })
- it('should truncate with custom ellipsis', function () {
- return test('{{ "Ground control to Major Tom." | truncate: 25,", and so on" }}',
- 'Ground control, and so on')
- })
- it('should truncate with empty custom ellipsis', function () {
- return test('{{ "Ground control to Major Tom." | truncate: 20, "" }}',
- 'Ground control to Ma')
- })
- it('should not truncate when short enough', function () {
- return test('{{ "12345" | truncate: 5 }}', '12345')
- })
- it('should default to 16', function () {
- return test('{{ "1234567890abcdefghi" | truncate }}', '1234567890abc...')
- })
- })
-
- describe('truncatewords', function () {
- it('should truncate when too many words', function () {
- return test('{{ "Ground control to Major Tom." | truncatewords: 3 }}',
- 'Ground control to...')
- })
- it('should not truncate when not enough words', function () {
- return test('{{ "Ground control to Major Tom." | truncatewords: 8 }}',
- 'Ground control to Major Tom.')
- })
- it('should truncate with custom ellipsis', function () {
- return test('{{ "Ground control to Major Tom." | truncatewords: 3, "--" }}',
- 'Ground control to--')
- })
- it('should truncate with empty custom ellipsis', function () {
- return test('{{ "Ground control to Major Tom." | truncatewords: 3, "" }}',
- 'Ground control to')
- })
- })
-
- describe('uniq', function () {
- it('should uniq string list', function () {
- return test(
- '{% assign my_array = "ants, bugs, bees, bugs, ants" | split: ", " %}' +
- '{{ my_array | uniq | join: ", " }}',
- 'ants, bugs, bees'
- )
- })
- it('should uniq falsy value', function () {
- return test('{{"" | uniq | join: ","}}', '')
- })
- })
-
- it('should support upcase', () => test('{{ "Parker Moore" | upcase }}', 'PARKER MOORE'))
-
- describe('url_decode', function () {
- it('should decode %xx and +',
- () => test('{{ "%27Stop%21%27+said+Fred" | url_decode }}', "'Stop!' said Fred"))
- })
-
- describe('url_encode', function () {
- it('should encode @',
- () => test('{{ "john@liquid.com" | url_encode }}', 'john%40liquid.com'))
- it('should encode ',
- () => test('{{ "Tetsuro Takara" | url_encode }}', 'Tetsuro+Takara'))
- })
-
- describe('obj_test', function () {
- before(() => {
- liquid.registerFilter('obj_test', function () {
- return Array.prototype.slice.call(arguments).join(',')
- })
- })
- it('should support object', () => test(`{{ "a" | obj_test: k1: "v1", k2: foo }}`, 'a,k1,v1,k2,bar'))
- it('should support mixed object', () => test(`{{ "a" | obj_test: "something", k1: "v1", k2: foo }}`, 'a,something,k1,v1,k2,bar'))
- })
-})
diff --git a/test/unit/fs/browser.ts b/test/unit/fs/browser.ts
new file mode 100644
index 000000000..3dd4a8de4
--- /dev/null
+++ b/test/unit/fs/browser.ts
@@ -0,0 +1,84 @@
+import fs from 'src/fs/browser'
+import * as sinon from 'sinon'
+import { expect, use } from 'chai'
+import * as chaiAsPromised from 'chai-as-promised'
+
+use(chaiAsPromised)
+const resolve = fs.resolve
+
+describe('fs/browser', function () {
+ describe('#resolve()', function () {
+ if (+process.version.match(/^v(\d+)/)[1] < 8) {
+ console.info('jsdom not supported, skipping template-browser...')
+ return
+ }
+ const JSDOM = require('jsdom').JSDOM
+ beforeEach(function () {
+ const dom = new JSDOM(``, {
+ url: 'https://example.com/foo/bar/',
+ contentType: 'text/html',
+ includeNodeLocations: true
+ });
+ (global as any).document = dom.window.document
+ })
+ afterEach(function () {
+ delete (global as any).document
+ })
+ it('should support relative root', function () {
+ expect(resolve('./views/', 'foo', '')).to.equal('https://example.com/foo/bar/views/foo')
+ })
+ it('should treat root as directory', function () {
+ expect(resolve('./views', 'foo', '')).to.equal('https://example.com/foo/bar/views/foo')
+ })
+ it('should support absolute root', function () {
+ expect(resolve('/views', 'foo', '')).to.equal('https://example.com/views/foo')
+ })
+ it('should support empty root', function () {
+ expect(resolve('', 'page.html', '')).to.equal('https://example.com/foo/bar/page.html')
+ })
+ it('should support full url as root', function () {
+ expect(resolve('https://example.com/views/', 'page.html', '')).to.equal('https://example.com/views/page.html')
+ })
+ it('should add extname when absent', function () {
+ expect(resolve('https://example.com/views/', 'page', '.html')).to.equal('https://example.com/views/page.html')
+ })
+ it('should add extname for urls have searchParams', function () {
+ expect(resolve('https://example.com/views/', 'page?foo=bar', '.html')).to.equal('https://example.com/views/page.html?foo=bar')
+ })
+ it('should not add extname when full url is given', function () {
+ expect(resolve('https://example.com/views/', 'https://google.com/page.php', '.html')).to.equal('https://google.com/page.php')
+ })
+ it('should not add extname when already have one', function () {
+ expect(resolve('https://example.com/views/', 'page.php', '.html')).to.equal('https://example.com/views/page.php')
+ })
+ })
+
+ describe('#readFile()', () => {
+ let server
+ beforeEach(() => {
+ server = sinon.createFakeServer()
+ server.autoRespond = true
+ server.respondWith('GET', 'https://example.com/views/hello.html',
+ [200, { 'Content-Type': 'text/plain' }, 'hello {{name}}']);
+ (global as any).XMLHttpRequest = sinon.useFakeXMLHttpRequest()
+ })
+ afterEach(() => {
+ server.restore()
+ delete (global as any).XMLHttpRequest
+ })
+ it('should get corresponding text', async function () {
+ const html = await fs.readFile('https://example.com/views/hello.html')
+ return expect(html).to.equal('hello {{name}}')
+ })
+ it('should throw 404', () => {
+ return expect(fs.readFile('https://example.com/not/exist.html'))
+ .to.be.rejectedWith('Not Found')
+ })
+ it('should throw error', function () {
+ const result = expect(fs.readFile('https://example.com/views/hello.html'))
+ .to.be.rejectedWith('An error occurred whilst receiving the response.')
+ server.requests[0].error()
+ return result
+ })
+ })
+})
diff --git a/test/unit/fs/node.ts b/test/unit/fs/node.ts
new file mode 100644
index 000000000..c7ec20212
--- /dev/null
+++ b/test/unit/fs/node.ts
@@ -0,0 +1,47 @@
+import fs from 'src/fs/node'
+import * as path from 'path'
+import { expect, use } from 'chai'
+import * as chaiAsPromised from 'chai-as-promised'
+import { mock, restore } from 'test/stub/mockfs'
+
+use(chaiAsPromised)
+
+describe('fs', function () {
+ before(() => mock({
+ '/foo/bar.html': 'bar',
+ '/un-readable.html': { mode: '0000', content: '' }
+ }))
+ after(restore)
+
+ describe('#resolve()', function () {
+ it('should resolve based on root', async function () {
+ const filepath = fs.resolve('/foo', 'bar.html', '.liquid')
+ const expected = path.resolve('/foo/bar.html')
+ return expect(filepath).to.equal(expected)
+ })
+ it('should add extension if it has no extension', async function () {
+ const filepath = fs.resolve('/foo', 'bar', '.liquid')
+ const expected = path.resolve('/foo/bar.liquid')
+ return expect(filepath).to.equal(expected)
+ })
+ })
+ describe('#exists', () => {
+ it('should resolve as false if not exists', async () => {
+ const result = await fs.exists('/foo/foo.html')
+ return expect(result).to.be.false
+ })
+ it('should resolve as true if exists', async () => {
+ const result = await fs.exists('/foo/bar.html')
+ return expect(result).to.be.true
+ })
+ })
+ describe('#readFile', function () {
+ it('should throw when not exist', function () {
+ return expect(fs.readFile('/foo/foo.html')).to.rejectedWith('ENOENT')
+ })
+ it('should throw when file not readable', function () {
+ return expect(fs.readFile('/un-readable.html')).to
+ .be.rejectedWith(/EACCES/)
+ })
+ })
+})
diff --git a/test/unit/options/cache.ts b/test/unit/liquid/cache.ts
similarity index 100%
rename from test/unit/options/cache.ts
rename to test/unit/liquid/cache.ts
diff --git a/test/unit/liquid.ts b/test/unit/liquid/liquid.ts
similarity index 87%
rename from test/unit/liquid.ts
rename to test/unit/liquid/liquid.ts
index a12014b57..6535fc3d8 100644
--- a/test/unit/liquid.ts
+++ b/test/unit/liquid/liquid.ts
@@ -1,15 +1,10 @@
-import Liquid from '../../src/liquid'
+import Liquid from 'src/liquid'
import * as chai from 'chai'
import { mock, restore } from 'test/stub/mockfs'
const expect = chai.expect
describe('Liquid', function () {
- describe('#constructor()', function () {
- it('should throw on illegal root', function () {
- expect(() => new (Liquid as any)({ root: {} })).to.throw(/illegal root/)
- })
- })
describe('#plugin()', function () {
it('should call plugin on the instance', async function () {
const engine = new Liquid()
diff --git a/test/unit/options/strict.ts b/test/unit/liquid/strict.ts
similarity index 100%
rename from test/unit/options/strict.ts
rename to test/unit/liquid/strict.ts
diff --git a/test/unit/options/trimming.ts b/test/unit/liquid/trimming.ts
similarity index 98%
rename from test/unit/options/trimming.ts
rename to test/unit/liquid/trimming.ts
index 63666c4be..55e6d5043 100644
--- a/test/unit/options/trimming.ts
+++ b/test/unit/liquid/trimming.ts
@@ -1,5 +1,5 @@
import { expect } from 'chai'
-import Liquid from '../../../src/liquid'
+import Liquid from 'src/liquid'
describe('LiquidOptions#trimming', function () {
const ctx = { name: 'harttle' }
diff --git a/test/unit/lexical.ts b/test/unit/parser/lexical.ts
similarity index 98%
rename from test/unit/lexical.ts
rename to test/unit/parser/lexical.ts
index 67d7d1736..bfb0bb325 100644
--- a/test/unit/lexical.ts
+++ b/test/unit/parser/lexical.ts
@@ -1,7 +1,7 @@
import * as chai from 'chai'
const expect = chai.expect
-const lexical = require('../../src/parser/lexical')
+const lexical = require('src/parser/lexical')
describe('lexical', function () {
it('should test filter syntax', function () {
diff --git a/test/unit/tokenizer.ts b/test/unit/parser/tokenizer.ts
similarity index 100%
rename from test/unit/tokenizer.ts
rename to test/unit/parser/tokenizer.ts
diff --git a/test/unit/render.ts b/test/unit/render/render.ts
similarity index 85%
rename from test/unit/render.ts
rename to test/unit/render/render.ts
index f80345cea..8d66f3b91 100644
--- a/test/unit/render.ts
+++ b/test/unit/render/render.ts
@@ -1,9 +1,9 @@
import { expect } from 'chai'
-import Scope from '../../src/scope/scope'
-import Token from '../../src/parser/token'
+import Scope from 'src/scope/scope'
+import Token from 'src/parser/token'
import Tag from 'src/template/tag/tag'
import Filter from 'src/template/filter'
-import Render from '../../src/render/render'
+import Render from 'src/render/render'
import HTML from 'src/template/html'
describe('render', function () {
diff --git a/test/unit/syntax.ts b/test/unit/render/syntax.ts
similarity index 100%
rename from test/unit/syntax.ts
rename to test/unit/render/syntax.ts
diff --git a/test/unit/scope.ts b/test/unit/scope/scope.ts
similarity index 100%
rename from test/unit/scope.ts
rename to test/unit/scope/scope.ts
diff --git a/test/unit/template-browser.ts b/test/unit/template-browser.ts
deleted file mode 100644
index 8989c3d02..000000000
--- a/test/unit/template-browser.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { resolve } from '../../src/parser/template-browser'
-import { expect } from 'chai'
-
-describe('template-browser', function () {
- if (+process.version.match(/^v(\d+)/)[1] < 8) {
- console.info('jsdom not supported, skipping template-browser...')
- return
- }
- const JSDOM = require('jsdom').JSDOM
- beforeEach(function () {
- const dom = new JSDOM(``, {
- url: 'https://example.com/foo/bar/',
- contentType: 'text/html',
- includeNodeLocations: true
- });
- (global as any).document = dom.window.document
- })
- afterEach(function () {
- delete (global as any).document
- })
- describe('resolve', function () {
- it('should support relative root', function () {
- expect(resolve('foo', './views/', {
- extname: '',
- root: ['.']
- })).to.equal('https://example.com/foo/bar/views/foo')
- })
- it('should treat root as directory', function () {
- expect(resolve('foo', './views', {
- extname: '',
- root: ['.']
- })).to.equal('https://example.com/foo/bar/views/foo')
- })
- it('should support absolute root', function () {
- expect(resolve('foo', '/views', {
- extname: '',
- root: ['.']
- })).to.equal('https://example.com/views/foo')
- })
- it('should support empty root', function () {
- expect(resolve('page.html', '', {
- extname: '',
- root: ['.']
- })).to.equal('https://example.com/foo/bar/page.html')
- })
- it('should support full url as root', function () {
- expect(resolve('page.html', 'https://example.com/views/', {
- extname: '',
- root: ['.']
- })).to.equal('https://example.com/views/page.html')
- })
- it('should use options.root when root argument absent', function () {
- expect(resolve('page.html', null, {
- extname: '',
- root: ['https://example.com/views', 'https://google.com/views']
- })).to.equal('https://example.com/views/page.html')
- })
- it('should add extname when absent', function () {
- expect(resolve('page', 'https://example.com/views/', {
- extname: '.html',
- root: ['.']
- })).to.equal('https://example.com/views/page.html')
- })
- it('should add extname for urls have searchParams', function () {
- expect(resolve('page?foo=bar', 'https://example.com/views/', {
- extname: '.html',
- root: ['.']
- })).to.equal('https://example.com/views/page.html?foo=bar')
- })
- it('should not add extname when full url is given', function () {
- expect(resolve('https://google.com/page.php', 'https://example.com/views/', {
- extname: '.html',
- root: ['.']
- })).to.equal('https://google.com/page.php')
- })
- it('should not add extname when already have one', function () {
- expect(resolve('page.php', 'https://example.com/views/', {
- extname: '.html',
- root: ['.']
- })).to.equal('https://example.com/views/page.php')
- })
- })
-})
diff --git a/test/unit/template.ts b/test/unit/template.ts
deleted file mode 100644
index d23102e7b..000000000
--- a/test/unit/template.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { resolve } from '../../src/parser/template'
-import * as path from 'path'
-import { expect, use } from 'chai'
-import * as chaiAsPromised from 'chai-as-promised'
-import { mock, restore } from '../stub/mockfs'
-
-use(chaiAsPromised)
-
-describe('template', function () {
- before(() => mock({ '/foo/bar.html': 'bar' }))
- after(restore)
-
- describe('#resolve()', function () {
- it('should resolve based on root', async function () {
- const filepath = await resolve('bar.html', '/foo', { root: [] })
- const expected = path.resolve('/foo/bar.html')
- return expect(filepath).to.equal(expected)
- })
- it('should resolve based on root', function () {
- return expect(resolve('foo.html', '/foo', { root: [] }))
- .to.rejectedWith(/Failed to lookup foo.html in: \/foo/)
- })
- })
-})
diff --git a/test/unit/filter.ts b/test/unit/template/filter.ts
similarity index 100%
rename from test/unit/filter.ts
rename to test/unit/template/filter.ts
diff --git a/test/unit/output.ts b/test/unit/template/output.ts
similarity index 96%
rename from test/unit/output.ts
rename to test/unit/template/output.ts
index 0d970af41..6a1cd3874 100644
--- a/test/unit/output.ts
+++ b/test/unit/template/output.ts
@@ -1,6 +1,6 @@
import * as chai from 'chai'
-import Scope from '../../src/scope/scope'
-import Output from '../../src/template/output'
+import Scope from 'src/scope/scope'
+import Output from 'src/template/output'
import OutputToken from 'src/parser/output-token'
import Filter from 'src/template/filter'
diff --git a/test/unit/tag.ts b/test/unit/template/tag.ts
similarity index 100%
rename from test/unit/tag.ts
rename to test/unit/template/tag.ts
diff --git a/test/unit/value.ts b/test/unit/template/value.ts
similarity index 98%
rename from test/unit/value.ts
rename to test/unit/template/value.ts
index 2941081dc..bfa46d5f6 100644
--- a/test/unit/value.ts
+++ b/test/unit/template/value.ts
@@ -1,7 +1,7 @@
import * as chai from 'chai'
import * as sinonChai from 'sinon-chai'
import * as sinon from 'sinon'
-import Scope from '../../src/scope/scope'
+import Scope from 'src/scope/scope'
import Filter from 'src/template/filter'
import Value from 'src/template/value'
diff --git a/test/unit/util/assert.ts b/test/unit/util/assert.ts
index 046b06ed5..acf94ff4e 100644
--- a/test/unit/util/assert.ts
+++ b/test/unit/util/assert.ts
@@ -1,5 +1,5 @@
import * as chai from 'chai'
-import assert from '../../../src/util/assert'
+import assert from 'src/util/assert'
const expect = chai.expect
diff --git a/test/unit/util/promise.ts b/test/unit/util/promise.ts
index 8747abb69..661e02e18 100644
--- a/test/unit/util/promise.ts
+++ b/test/unit/util/promise.ts
@@ -5,7 +5,7 @@ import * as sinonChai from 'sinon-chai'
const expect = chai.expect
chai.use(sinonChai)
-const P = require('../../../src/util/promise')
+const P = require('src/util/promise')
describe('util/promise', function () {
describe('.anySeries()', function () {
diff --git a/test/unit/util/strftime.ts b/test/unit/util/strftime.ts
index 035f47e17..16ccbd1e4 100644
--- a/test/unit/util/strftime.ts
+++ b/test/unit/util/strftime.ts
@@ -1,5 +1,5 @@
import * as chai from 'chai'
-import t from '../../../src/util/strftime'
+import t from 'src/util/strftime'
const expect = chai.expect
diff --git a/test/unit/util/underscore.ts b/test/unit/util/underscore.ts
index 1e0076d85..f03540dbf 100644
--- a/test/unit/util/underscore.ts
+++ b/test/unit/util/underscore.ts
@@ -1,8 +1,8 @@
import * as chai from 'chai'
import * as sinonChai from 'sinon-chai'
import * as sinon from 'sinon'
-import { RenderError, RenderBreakError } from '../../../src/util/error'
-import * as _ from '../../../src/util/underscore'
+import { RenderError, RenderBreakError } from 'src/util/error'
+import * as _ from 'src/util/underscore'
const expect = chai.expect
chai.use(sinonChai)
diff --git a/test/unit/xhr.ts b/test/unit/xhr.ts
deleted file mode 100644
index 94bdc6d77..000000000
--- a/test/unit/xhr.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { read } from 'src/parser/template-browser'
-import * as sinon from 'sinon'
-import { expect, use } from 'chai'
-import * as chaiAsPromised from 'chai-as-promised'
-
-use(chaiAsPromised)
-
-describe('xhr', () => {
- if (+process.version.match(/^v(\d+)/)[1] < 8) {
- console.info('jsdom not supported, skipping xhr...')
- return
- }
- let server
- beforeEach(() => {
- server = sinon.createFakeServer()
- server.autoRespond = true
- server.respondWith('GET', 'https://example.com/views/hello.html',
- [200, { 'Content-Type': 'text/plain' }, 'hello {{name}}']);
- (global as any).XMLHttpRequest = sinon.useFakeXMLHttpRequest()
- })
- afterEach(() => {
- server.restore()
- delete (global as any).XMLHttpRequest
- })
- describe('#read()', () => {
- it('should get corresponding text', async function () {
- const html = await read('https://example.com/views/hello.html')
- return expect(html).to.equal('hello {{name}}')
- })
- it('should throw 404', () => {
- return expect(read('https://example.com/not/exist.html'))
- .to.be.rejectedWith('Not Found')
- })
- it('should throw error', function (done) {
- read('https://example.com/views/hello.html')
- .then(() => done('should not be resolved'))
- .catch(function (e) {
- expect(e.message).to.equal('An error occurred whilst receiving the response.')
- done()
- })
- server.requests[0].error()
- })
- })
-})
diff --git a/tsconfig.json b/tsconfig.json
index c8317eb48..7cc23e7ae 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,7 +10,7 @@
"emitDecoratorMetadata": true,
"baseUrl": ".",
"paths": {
- "template": ["src/parser/template"],
+ "src/fs": ["src/fs/node"],
"src/*": ["src/*"],
"test/*": ["test/*"]
}