refactor tests
This commit is contained in:
parent
f30717a9fa
commit
3aaa48aa59
14 changed files with 242 additions and 113 deletions
|
@ -25,6 +25,7 @@ export const apply = curry((v, f) => f(v))
|
|||
export const reduce = curry((fn, init, v) => v.reduce(fn, init))
|
||||
export const map = curry((fn, v) => v.map(fn))
|
||||
export const filter = curry((fn, v) => v.filter(fn))
|
||||
export const find = curry((fn, v) => v.find(fn))
|
||||
export const join = curry((sep, v) => v.join(sep))
|
||||
export const pipe = (...f) => v => f.reduce(apply, v)
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ export const seq = (...parsers) => state => {
|
|||
let acc = Result.Ok(state)
|
||||
for (const parser of parsers) {
|
||||
if (acc.isOk()) {
|
||||
acc = parser(acc.value)
|
||||
acc = parser(acc.unwrap())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
@ -100,11 +100,11 @@ export const until = curry((parser, state) => {
|
|||
let acc = Result.Ok(state)
|
||||
|
||||
while (acc.isOk()) {
|
||||
const result = parser(clone(acc.value))
|
||||
const result = parser(clone(acc.unwrap()))
|
||||
if (result.isOk()) {
|
||||
break
|
||||
} else {
|
||||
acc = anyChar(acc.value)
|
||||
acc = anyChar(acc.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ export const many = curry((parser, state) => {
|
|||
let result = Result.Ok(state)
|
||||
|
||||
while (true) {
|
||||
const res = parser(clone(result.value))
|
||||
const res = parser(clone(result.unwrap()))
|
||||
if (res.isOk()) {
|
||||
result = res
|
||||
} else {
|
||||
|
@ -131,7 +131,7 @@ export const skip = curry((parser, state) => {
|
|||
const result = parser(state)
|
||||
|
||||
if (result.isOk()) {
|
||||
return Result.Ok([parsed, result.value[1]])
|
||||
return Result.Ok([parsed, result.unwrap()[1]])
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
|
@ -142,11 +142,11 @@ export const map = curry((fn, parser, state) => {
|
|||
|
||||
if (result.isOk()) {
|
||||
const [parsed] = state
|
||||
const [, stream] = result.value
|
||||
const [, stream] = result.unwrap()
|
||||
const backtrack = [parsed, stream]
|
||||
|
||||
try {
|
||||
const parsedValue = diff(state, result.value)
|
||||
const parsedValue = diff(state, result.unwrap())
|
||||
return succeed(fn(parsedValue), backtrack)
|
||||
} catch (e) {
|
||||
return fail('map failed', state, e)
|
||||
|
@ -201,7 +201,7 @@ export const noCaseString = curry((str, state) => (
|
|||
))
|
||||
|
||||
export const maybe = curry((parser, state) => {
|
||||
const result = parser(state)
|
||||
const result = parser(clone(state))
|
||||
return result.isOk() ? result : succeed([], state)
|
||||
})
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { join } from '../fn.js'
|
||||
import { alpha, alphanumeric, any, char, digit, list, many, map, maybe, noCaseString, separated, seq, skip, string, until } from '../parser.js'
|
||||
import { Alias, Literal, ObjectPath } from './types.js'
|
||||
import { Alias, Identifier, Literal, ObjectPath } from './types.js'
|
||||
|
||||
export const Symbol = Object.freeze({
|
||||
Bracket: Object.freeze({
|
||||
|
@ -37,7 +37,7 @@ export const quoted = collect(seq(skip(Symbol.Quote), until(Symbol.Quote), skip(
|
|||
export const number = seq(digit, many(digit))
|
||||
export const signed = seq(maybe(any(Symbol.Plus, Symbol.Hyphen)), number)
|
||||
export const ws = skip(many(Symbol.Space))
|
||||
export const identifier = collect(seq(alpha, many(alphanumeric)))
|
||||
export const identifier = map(([x]) => new Identifier(x), collect(seq(alpha, many(alphanumeric))))
|
||||
|
||||
const float = map(([n]) => parseFloat(n, 10), collect(seq(signed, Symbol.Period, number)))
|
||||
const integer = map(([n]) => parseInt(n, 10), collect(signed))
|
||||
|
|
|
@ -1,43 +1,48 @@
|
|||
import { collect, Symbol, ws } from './common.js'
|
||||
import { identifier, literal, Symbol, ws } from './common.js'
|
||||
import { Node, Edge, KeyValuePair, Label, Name } from './types.js'
|
||||
import { curry, join } from '../fn.js'
|
||||
import { alpha, alphanumeric, many, maybe, map, parse, seq, skip, between, noCaseString, separated, until, list } from '../parser.js'
|
||||
import { curry, is } from '../fn.js'
|
||||
import { many, maybe, map, seq, skip, between, noCaseString, separated, list } from '../parser.js'
|
||||
|
||||
const { Bracket, Colon, Comma, Hyphen, Quote } = Symbol
|
||||
const { Bracket, Colon, Comma, Hyphen } = Symbol
|
||||
|
||||
const name = map(
|
||||
([x]) => new Name(x),
|
||||
collect(seq(alpha, many(alphanumeric)))
|
||||
identifier
|
||||
)
|
||||
|
||||
const label = map(([x]) => new Label(x), seq(skip(Colon), name))
|
||||
|
||||
const trim = curry((parser, state) => (
|
||||
between(ws, parser, ws, state)
|
||||
))
|
||||
|
||||
const label = map(([x]) => new Label(x), seq(trim(skip(Colon)), identifier))
|
||||
|
||||
const bracketed = curry((value, { Left, Right }, state) => (
|
||||
between(trim(Left), value, trim(Right), state)
|
||||
))
|
||||
|
||||
const quoted = map(join(''), seq(skip(Quote), until(Quote), skip(Quote)))
|
||||
const kvp = map(
|
||||
([k, v]) => new KeyValuePair(k, v),
|
||||
separated(name, trim(Colon), quoted)
|
||||
separated(name, trim(Colon), literal)
|
||||
)
|
||||
const kvps = list(trim(Comma), kvp)
|
||||
export const kvps = list(trim(Comma), kvp)
|
||||
export const properties = bracketed(kvps, Bracket.Curly)
|
||||
|
||||
const id = seq(maybe(name), label)
|
||||
|
||||
const makeObj = Ctr => params => {
|
||||
const [name, label] = is(Name, params[0]) ? [params[0], params[1]] : [undefined, params[0]]
|
||||
const properties = !name ? params.slice(1) : params.slice(2)
|
||||
return new Ctr(name, label, properties)
|
||||
}
|
||||
|
||||
export const node = map(
|
||||
([name, label, ...properties]) => new Node(name, label, properties),
|
||||
bracketed(seq(id, ws, maybe(properties)), Bracket.Round)
|
||||
makeObj(Node),
|
||||
bracketed(seq(id, maybe(properties)), Bracket.Round)
|
||||
)
|
||||
|
||||
export const edge = map(
|
||||
([id]) => new Edge(id),
|
||||
bracketed(id, Bracket.Square)
|
||||
makeObj(Edge),
|
||||
bracketed(seq(id, maybe(properties)), Bracket.Square)
|
||||
)
|
||||
|
||||
const rightArrow = seq(Hyphen, Bracket.Angle.Right)
|
||||
|
@ -45,5 +50,6 @@ const relationship = seq(skip(Hyphen), edge, skip(rightArrow), node)
|
|||
|
||||
const keyword = noCaseString('match')
|
||||
const params = seq(node, many(relationship))
|
||||
|
||||
export const statement = seq(skip(keyword), ws, params)
|
||||
|
||||
|
|
|
@ -4,12 +4,10 @@ import { value, Symbol, ws } from './common.js'
|
|||
|
||||
const keyword = noCaseString('return')
|
||||
|
||||
//const params = map(
|
||||
// values => new ReturnValues(values),
|
||||
// seq(list(seq(Symbol.Comma, ws), alias))
|
||||
//)
|
||||
|
||||
const params = seq(list(seq(ws, Symbol.Comma, ws), value))
|
||||
const params = map(
|
||||
x => new ReturnValues(...x),
|
||||
seq(list(seq(ws, Symbol.Comma, ws), value))
|
||||
)
|
||||
|
||||
export const statement = seq(skip(keyword), ws, params)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export class SelectedGraph {
|
|||
}
|
||||
|
||||
class GraphObject {
|
||||
constructor({ name, label }, properties = []) {
|
||||
constructor(name, label, properties = []) {
|
||||
this.name = name
|
||||
this.label = label
|
||||
this.properties = properties
|
||||
|
@ -25,20 +25,20 @@ class GraphObject {
|
|||
}
|
||||
|
||||
export class Node extends GraphObject {
|
||||
constructor(id, properties) {
|
||||
super(id, properties)
|
||||
constructor(name, label, properties) {
|
||||
super(name, label, properties)
|
||||
}
|
||||
}
|
||||
|
||||
export class Edge extends GraphObject {
|
||||
constructor(id, properties) {
|
||||
super(id, properties)
|
||||
constructor(name, label, properties) {
|
||||
super(name, label, properties)
|
||||
}
|
||||
}
|
||||
|
||||
export class ReturnValues extends Array {
|
||||
constructor(args) {
|
||||
super(args)
|
||||
constructor(...args) {
|
||||
super(...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
export class Result {
|
||||
#value
|
||||
#error
|
||||
|
||||
constructor(value, error) {
|
||||
this.value = value
|
||||
this.error = error
|
||||
this.#value = value
|
||||
this.#error = error
|
||||
}
|
||||
|
||||
static Ok(value) {
|
||||
|
@ -13,7 +16,7 @@ export class Result {
|
|||
}
|
||||
|
||||
isOk() {
|
||||
return this.error === null
|
||||
return this.#error === null
|
||||
}
|
||||
|
||||
isErr() {
|
||||
|
@ -22,7 +25,7 @@ export class Result {
|
|||
|
||||
map(fn) {
|
||||
if (this.isOk()) {
|
||||
return Result.Ok(fn(this.value))
|
||||
return Result.Ok(fn(this.#value))
|
||||
} else {
|
||||
return this
|
||||
}
|
||||
|
@ -30,11 +33,29 @@ export class Result {
|
|||
|
||||
flatMap(fn) {
|
||||
if (this.isOk()) {
|
||||
return fn(this.value)
|
||||
return fn(this.#value)
|
||||
} else {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
unwrap() {
|
||||
if (this.isOk()) {
|
||||
return this.#value
|
||||
} else {
|
||||
throw new ResultError(`failed to unwrap result: ${this.#error.message}`, this)
|
||||
}
|
||||
}
|
||||
|
||||
unwrapOr(value) {
|
||||
return this.isOk() ? this.#value : value
|
||||
}
|
||||
}
|
||||
|
||||
export class ResultError extends TypeError {
|
||||
constructor(msg, result) {
|
||||
super(msg)
|
||||
this.result = result
|
||||
}
|
||||
}
|
||||
|
||||
|
|
31
tests/assert.js
Normal file
31
tests/assert.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import assert from 'node:assert'
|
||||
import { curry } from '../src/fn.js'
|
||||
import { parse } from 'node:path'
|
||||
|
||||
const isOk = curry((fn, result) => {
|
||||
assert.doesNotThrow(() => {
|
||||
const [[actual]] = result.unwrap()
|
||||
fn(actual)
|
||||
})
|
||||
})
|
||||
|
||||
const isErr = (result, error, msg) => {
|
||||
if (error == null) {
|
||||
assert(result.isErr())
|
||||
} else {
|
||||
assert.throws(result.unwrap(), error, msg)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
...assert,
|
||||
parseOk: curry((parser, input, fn) => {
|
||||
isOk(fn, parse(parser, input))
|
||||
}),
|
||||
parseErr: (parser, input, error, message) => {
|
||||
isErr(parse(parser, input), error, message)
|
||||
},
|
||||
isOk,
|
||||
isErr
|
||||
}
|
||||
|
|
@ -2,8 +2,9 @@ import { describe, it } from 'node:test'
|
|||
import assert from 'node:assert'
|
||||
import { parse } from '../../src/parser.js'
|
||||
import * as Common from '../../src/query/common.js'
|
||||
import { Alias, ObjectPath } from '../../src/query/types.js'
|
||||
import { Alias, Identifier, Literal, ObjectPath } from '../../src/query/types.js'
|
||||
|
||||
const v = r => r.unwrap()[0][0]
|
||||
describe('common parser library', () => {
|
||||
it('literals should match literal types', () => {
|
||||
const tBool = parse(Common.literal, 'true')
|
||||
|
@ -16,16 +17,15 @@ describe('common parser library', () => {
|
|||
const negFloat = parse(Common.literal, '-12.01')
|
||||
const string = parse(Common.literal, '"akjsdfuaio"')
|
||||
|
||||
const v = r => r.value[0][0].value
|
||||
assert.strictEqual(v(tBool), true)
|
||||
assert.strictEqual(v(fBool), false)
|
||||
assert.strictEqual(v(uint), 5)
|
||||
assert.strictEqual(v(posInt), 16)
|
||||
assert.strictEqual(v(negInt), -710)
|
||||
assert.strictEqual(v(ufloat), 2.1)
|
||||
assert.strictEqual(v(posFloat), 0.1)
|
||||
assert.strictEqual(v(negFloat), -12.01)
|
||||
assert.strictEqual(v(string), 'akjsdfuaio')
|
||||
assert.deepEqual(v(tBool), new Literal(true))
|
||||
assert.deepEqual(v(fBool), new Literal(false))
|
||||
assert.deepEqual(v(uint), new Literal(5))
|
||||
assert.deepEqual(v(posInt), new Literal(16))
|
||||
assert.deepEqual(v(negInt), new Literal(-710))
|
||||
assert.deepEqual(v(ufloat), new Literal(2.1))
|
||||
assert.deepEqual(v(posFloat), new Literal(0.1))
|
||||
assert.deepEqual(v(negFloat), new Literal(-12.01))
|
||||
assert.deepEqual(v(string), new Literal('akjsdfuaio'))
|
||||
})
|
||||
|
||||
it('value should match literals', () => {
|
||||
|
@ -34,29 +34,26 @@ describe('common parser library', () => {
|
|||
const float = parse(Common.baseValue, '0.15')
|
||||
const str = parse(Common.baseValue, '"abc"')
|
||||
|
||||
const v = r => r.value[0][0].value
|
||||
assert.strictEqual(v(bool), false)
|
||||
assert.strictEqual(v(uint), 11)
|
||||
assert.strictEqual(v(float), 0.15)
|
||||
assert.strictEqual(v(str), 'abc')
|
||||
assert.deepEqual(v(bool), new Literal(false))
|
||||
assert.deepEqual(v(uint), new Literal(11))
|
||||
assert.deepEqual(v(float), new Literal(0.15))
|
||||
assert.deepEqual(v(str), new Literal('abc'))
|
||||
})
|
||||
|
||||
it('value should match variables', () => {
|
||||
const identifier = parse(Common.baseValue, 'test')
|
||||
const accessor = parse(Common.baseValue, 'test.value')
|
||||
const v = r => r.value[0][0]
|
||||
assert.strictEqual(v(identifier), 'test')
|
||||
assert.deepEqual(v(accessor), new ObjectPath('test', 'value'))
|
||||
assert.deepEqual(v(identifier), new Identifier('test'))
|
||||
assert.deepEqual(v(accessor), new ObjectPath(new Identifier('test'), new Identifier('value')))
|
||||
})
|
||||
|
||||
it('aliases should work i hope', () => {
|
||||
const noAlias = parse(Common.value, 'test')
|
||||
const aliased1 = parse(Common.value, 'crybaby AS cb')
|
||||
const aliased2 = parse(Common.value, 'property.name AS name')
|
||||
const v = r => r.value[0][0]
|
||||
assert.strictEqual(v(noAlias), 'test')
|
||||
assert.deepEqual(v(aliased1), new Alias('crybaby', 'cb'))
|
||||
assert.deepEqual(v(aliased2), new Alias(new ObjectPath('property', 'name'), 'name'))
|
||||
assert.deepEqual(v(noAlias), new Identifier('test'))
|
||||
assert.deepEqual(v(aliased1), new Alias(new Identifier('crybaby'), new Identifier('cb')))
|
||||
assert.deepEqual(v(aliased2), new Alias(new ObjectPath(new Identifier('property'), new Identifier('name')), new Identifier('name')))
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,21 +1,89 @@
|
|||
import { describe, it } from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
import { parse } from '../../src/parser.js'
|
||||
import assert from '../assert.js'
|
||||
import { node, edge, properties, statement } from '../../src/query/match.js'
|
||||
import { makeEdge, makeNode } from '../utils.js'
|
||||
|
||||
//describe('match parser', () => {
|
||||
// it('node should match a label', () => {
|
||||
// const result = parse(node, '(:Node)')
|
||||
// console.log(result.error.state)
|
||||
// assert(result.isOk())
|
||||
// })
|
||||
//
|
||||
// it('properties should do something', () => {
|
||||
// const q = '(a:Node { name: "Rowan", species: "???" })'
|
||||
// console.log(
|
||||
// `parsing "${q}"\n`,
|
||||
// parse(node, q).value[0][0]
|
||||
// )
|
||||
// })
|
||||
//})
|
||||
describe('node', () => {
|
||||
it('should match a label with an empty name', () => {
|
||||
assert.parseOk(node, '(:Node)', actual => {
|
||||
const expected = makeNode(undefined, 'Node')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should match a name and label', () => {
|
||||
assert.parseOk(node, '(node:Node)', actual => {
|
||||
const expected = makeNode('node', 'Node')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should match a node with properties and no name', () => {
|
||||
assert.parseOk(node, '(:Label { name: "Rowan", gay: true })', actual => {
|
||||
const expected = makeNode(undefined, 'Label', [['name', 'Rowan'], ['gay', true]])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should match a node with properties and a name', () => {
|
||||
assert.parseOk(node, '(name:Label { name: "Rowan", gay: true })', actual => {
|
||||
const expected = makeNode('name', 'Label', [['name', 'Rowan'], ['gay', true]])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle whitespace', () => {
|
||||
assert.parseOk(node, '( name : Label { name : "Rowan" , gay : true } )', actual => {
|
||||
const expected = makeNode('name', 'Label', [['name', 'Rowan'], ['gay', true]])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('edge', () => {
|
||||
it('should match a relationship with a name and label', () => {
|
||||
assert.parseOk(edge, '[name:Label]', actual => {
|
||||
const expected = makeEdge('name', 'Label', [])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should match a relationship with no name', () => {
|
||||
assert.parseOk(edge, '[:Label]', actual => {
|
||||
const expected = makeEdge(undefined, 'Label', [])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should match a relationship with a name and properties', () => {
|
||||
assert.parseOk(edge, '[gay:Queer { binary: "-∞" }]', actual => {
|
||||
const expected = makeEdge('gay', 'Queer', [['binary', '-∞']])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should match a relationship with properties and no name', () => {
|
||||
assert.parseOk(edge, '[:Queer { binary: "-∞" }]', actual => {
|
||||
const expected = makeEdge(undefined, 'Queer', [['binary', '-∞']])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle whitespace', () => {
|
||||
assert.parseOk(edge, '[ : Queer { binary : "-∞" } ]', actual => {
|
||||
const expected = makeEdge(undefined, 'Queer', [['binary', '-∞']])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('match', () => {
|
||||
it('should match nodes', () => {
|
||||
assert.parseOk(statement, '(node:Label)', actual => {
|
||||
const expected = makeNode('node', 'Label')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
import { describe, it } from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
import { parse } from '../../src/parser.js'
|
||||
import assert from '../assert.js'
|
||||
import { statement } from '../../src/query/return.js'
|
||||
import { Alias } from '../../src/query/types.js'
|
||||
import { Alias, Identifier, Literal } from '../../src/query/types.js'
|
||||
|
||||
describe('return parser', () => {
|
||||
it('should collect a single value for a query to return', () => {
|
||||
const result = parse(statement, 'RETURN folklore AS f')
|
||||
assert(result.isOk())
|
||||
const [[selected]] = result.value
|
||||
assert.deepStrictEqual(selected, new Alias('folklore', 'f'))
|
||||
assert.parseOk(statement, 'RETURN folklore AS f', actual => {
|
||||
assert.deepEqual(actual, new Alias(new Identifier('folklore'), new Identifier('f')))
|
||||
})
|
||||
})
|
||||
|
||||
//it('should collect multiple values for a query to return', () => {
|
||||
// const result = parse(statement, 'RETURN sybil, mercury, rowan')
|
||||
// console.log(result.error.state[0])
|
||||
// assert(result.isOk())
|
||||
// const [[selected]] = result.value
|
||||
// assert.deepStrictEqual(selected, ['sybil', 'mercury', 'rowan'])
|
||||
//})
|
||||
it('should collect multiple values for a query to return', () => {
|
||||
assert.parseOk(statement, 'RETURN sybil, mercury, rowan', actual => {
|
||||
assert.deepStrictEqual(actual, ['sybil', 'mercury', 'rowan'].map(x => new Identifier(x)))
|
||||
})
|
||||
})
|
||||
|
||||
it('should accept mixed values and aliases', () => {
|
||||
assert.parseOk(statement, 'RETURN 19589 AS sybil, mercury AS vex, rowan', actual => {
|
||||
const sybil = new Alias(new Literal(19589), new Identifier('sybil'))
|
||||
const mercury = new Alias(new Identifier('mercury'), new Identifier('vex'))
|
||||
const rowan = new Identifier('rowan')
|
||||
assert.deepStrictEqual(actual, [sybil, mercury, rowan])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import { describe, it } from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
import assert from '../assert.js'
|
||||
import { parse } from '../../src/parser.js'
|
||||
import { statement } from '../../src/query/use.js'
|
||||
import { Identifier } from '../../src/query/types.js'
|
||||
|
||||
describe('use parser', () => {
|
||||
it('should select a graph to query', () => {
|
||||
const result = parse(statement, 'USE default')
|
||||
assert(result.isOk())
|
||||
const [[selected]] = result.value
|
||||
assert.strictEqual(selected.identifier, 'default')
|
||||
assert.parseOk(statement, 'USE default', actual => {
|
||||
assert.deepEqual(actual.identifier, new Identifier('default'))
|
||||
})
|
||||
})
|
||||
|
||||
it('should return an error if no graph identifier is provided', () => {
|
||||
const result = parse(statement, 'USE')
|
||||
assert(result.isErr())
|
||||
assert.parseErr(statement, 'USE')
|
||||
})
|
||||
})
|
||||
|
||||
|
|
10
tests/run.js
10
tests/run.js
|
@ -1,10 +0,0 @@
|
|||
import { tap } from 'node:test/reporters'
|
||||
import { run } from 'node:test'
|
||||
import path from 'node:path'
|
||||
|
||||
run({ files: [path.resolve('./tests/query/use.js')] })
|
||||
.on('test:fail', () => {
|
||||
process.exitCode = 1
|
||||
})
|
||||
.compose(tap)
|
||||
.pipe(process.stdout)
|
13
tests/utils.js
Normal file
13
tests/utils.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { KeyValuePair, Name, Label, Identifier, Literal, Edge } from '../src/query/types.js'
|
||||
|
||||
export const keyValuePair = ([k, v]) => new KeyValuePair(new Name(new Identifier(k)), new Literal(v))
|
||||
|
||||
export const graphObject = (name, label, props = [], Type = Node) => new Type(
|
||||
name && new Name(new Identifier(name)),
|
||||
new Label(new Identifier(label)),
|
||||
props.map(makeKvp)
|
||||
)
|
||||
|
||||
export const makeNode = graphObject
|
||||
export const makeEdge = (name, label, props) => graphObject(name, label, props, Edge)
|
||||
|
Loading…
Reference in a new issue