api-tuner 0.1.4 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,13 +46,13 @@ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
46
46
  PREFIX log: <http://www.w3.org/2000/10/swap/log#>
47
47
  PREFIX string: <http://www.w3.org/2000/10/swap/string#>
48
48
 
49
- :getExampleDotCom
49
+ <#getExampleDotCom>
50
50
  a earl:TestCase ;
51
51
  rdfs:label "Simple GET test" ;
52
52
  .
53
53
 
54
54
  # Configure a request
55
- :req
55
+ _:req
56
56
  a tuner:Request ;
57
57
  tuner:url <http://localhost:1080/example.com> ;
58
58
  tuner:method "GET" ;
@@ -60,7 +60,7 @@ PREFIX string: <http://www.w3.org/2000/10/swap/string#>
60
60
 
61
61
  {
62
62
  # Execute the request and capture its response
63
- :req tuner:response ?res .
63
+ _:req tuner:response ?res .
64
64
 
65
65
  # Check the response status code and content type
66
66
  ?res tuner:http_code 200 ;
@@ -71,7 +71,7 @@ PREFIX string: <http://www.w3.org/2000/10/swap/string#>
71
71
  ?res!tuner:body string:contains "Example Domain" .
72
72
  } => {
73
73
  # Use te EARL vocabulary to assert the test passed
74
- :getExampleDotCom earl:outcome earl:passed .
74
+ <#getExampleDotCom> earl:outcome earl:passed .
75
75
  } .
76
76
  ```
77
77
 
package/bin/tuner.sh CHANGED
@@ -79,14 +79,10 @@ if [ "$SILENT" != true ]; then
79
79
  ARGS="$ARGS ${SCRIPT_PATH}/../logging/info.n3"
80
80
  fi
81
81
 
82
- MERGED="$(mktemp)"
83
- if [ -n "$BASE_IRI" ]; then
84
- echo "base <$BASE_IRI>" > "$MERGED"
85
- fi
86
-
87
- for path in "${PATHS[@]}"; do
88
- cat "$path" >> "$MERGED"
89
- done
90
-
91
82
  set -o pipefail
92
- $eye $ARGS "${SCRIPT_PATH}"/../rules/*.n3 "${MERGED}" | $SUMMARY
83
+ for path in "${PATHS[@]}"; do
84
+ (
85
+ node "${SCRIPT_PATH}/../lib/parse-test-case.js" --base-iri "$BASE_IRI" -- "${path}" \
86
+ | $eye $ARGS "${SCRIPT_PATH}"/../rules/*.n3 -
87
+ ) ;
88
+ done | $SUMMARY
@@ -0,0 +1,39 @@
1
+ import * as url from 'node:url'
2
+ import { createReadStream } from 'node:fs'
3
+ import yargs from 'yargs'
4
+ import { hideBin } from 'yargs/helpers'
5
+ import replaceStream from 'replacestream'
6
+ import isAbsoluteUrl from 'is-absolute-url'
7
+ import StreamConcat from 'stream-concat'
8
+
9
+ const argv = yargs(hideBin(process.argv)).argv
10
+
11
+ const baseIri = argv['base-iri'] || 'http://example.org/'
12
+ const testCases = argv._
13
+
14
+ function replacer(fileUrl) {
15
+ return (_, match) => {
16
+ if (match.startsWith('#')) {
17
+ return `<${fileUrl}${match}>`
18
+ }
19
+
20
+ if (isAbsoluteUrl(match)) {
21
+ return `<${match}>`
22
+ }
23
+
24
+ return `<${baseIri}${match}>`
25
+ }
26
+ }
27
+
28
+ let fileIndex = 0
29
+ function nextStream() {
30
+ if (fileIndex === testCases.length) {
31
+ return null
32
+ }
33
+ const testCase = testCases[fileIndex++]
34
+ const testCaseUrl = url.pathToFileURL(testCase).toString()
35
+ return createReadStream(testCase)
36
+ .pipe(replaceStream(/<([^>]*)>(?=([^"\\]*(\\.|"([^"\\]*\\.)*[^"\\]*"))*[^"]*$)/g, replacer(testCaseUrl)))
37
+ }
38
+
39
+ new StreamConcat(nextStream).pipe(process.stdout)
@@ -28,15 +28,36 @@ const shapesTtl = new URL('./shapes.ttl', import.meta.url)
28
28
  const validationReport = validator.validate(data)
29
29
 
30
30
  if (argv.summary) {
31
- const testCases = rdf.clownface({ dataset: data }).has(rdf.ns.rdf.type, rdf.ns.earl.TestCase)
32
-
33
- for (const testCase of testCases.toArray()) {
34
- const result = validationReport.results.find(result => result.focusNode.equals(testCase.term))
35
- if (result?.severity.equals(rdf.ns.sh.Violation)) {
36
- process.stdout.write(`❌ FAIL <${testCase.value}>\n`)
37
- } else {
38
- process.stdout.write(`✅ PASS <${testCase.value}>\n`)
31
+ const resultMap = rdf.clownface({ dataset: data })
32
+ .has(rdf.ns.rdf.type, rdf.ns.earl.TestCase)
33
+ .toArray()
34
+ .reduce((map, testCase) => {
35
+ const { pathname } = new URL(testCase)
36
+
37
+ const testCases = map.get(pathname) || []
38
+ testCases.push(testCase)
39
+
40
+ return map.set(pathname, testCases)
41
+ }, new Map())
42
+
43
+ for (const [pathname, testCases] of resultMap.entries()) {
44
+ const summary = ['']
45
+ summary.push(`🔎 SUITE <file://${pathname}>`)
46
+
47
+ for (const testCase of testCases) {
48
+ const { hash } = new URL(testCase.value)
49
+ const result = validationReport.results.find(result => result.focusNode.equals(testCase.term))
50
+ const label = testCase.out(rdf.ns.rdfs.label).value
51
+ const resultLine = label ? `${label} (<${hash}>)` : `<${hash}>`
52
+
53
+ if (result?.severity.equals(rdf.ns.sh.Violation)) {
54
+ summary.push(`❌ FAIL ${resultLine}`)
55
+ } else {
56
+ summary.push(`✅ PASS ${resultLine}`)
57
+ }
39
58
  }
59
+
60
+ process.stderr.write(summary.join('\n') + '\n')
40
61
  }
41
62
  }
42
63
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-tuner",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -8,11 +8,11 @@
8
8
  "api-tuner": "./bin/tuner.sh"
9
9
  },
10
10
  "scripts": {
11
- "download-eye": "EYE_VERSION=11.5.2 ./lib/download-eye.sh",
11
+ "download-eye": "EYE_VERSION=11.10.0 ./lib/download-eye.sh",
12
12
  "postinstall": "([ -d eye ] || npm run download-eye) && eye/install.sh --prefix=eye",
13
13
  "prepare": "husky",
14
14
  "lint": "eslint . --quiet --ignore-path .gitignore",
15
- "test": "./bin/tuner.sh tests/*.n3 tests/**/*.n3",
15
+ "test": "./bin/tuner.sh tests/*.n3 tests/**/*.n3 --base-iri http://localhost:1080/",
16
16
  "release": "changeset publish"
17
17
  },
18
18
  "files": [
@@ -25,8 +25,11 @@
25
25
  "@changesets/cli": "^2.27.12",
26
26
  "@jeswr/pretty-turtle": "^1.5.0",
27
27
  "@zazuko/env-node": "^2.1.4",
28
+ "is-absolute-url": "^4.0.1",
28
29
  "jsonld": "^8.3.3",
29
30
  "rdf-validate-shacl": "^0.5.6",
31
+ "replacestream": "^4.0.3",
32
+ "stream-concat": "^2.0.0",
30
33
  "yargs": "^17.7.2"
31
34
  },
32
35
  "devDependencies": {
@@ -21,17 +21,31 @@ prefix log: <http://www.w3.org/2000/10/swap/log#>
21
21
 
22
22
  {
23
23
  ?res tuner:http_code ?value .
24
+ } <= {
25
+ ( ?res tuner:http_code ?value ) <#curl-field> [] .
26
+ } .
27
+
28
+ {
29
+ ?res tuner:url.host ?value .
30
+ } <= {
31
+ ( ?res tuner:url.host ?value ) <#curl-field> [] .
32
+ } .
33
+
34
+ {
35
+ ( ?res ?prop ?value ) <#curl-field> [] .
24
36
  } <= {
25
37
  ?res log:includes {
26
38
  [] a tuner:Response ;
27
- tuner:http_code ?actualValue .
39
+ ?prop ?actualValue .
28
40
  } .
29
41
 
42
+ ?prop log:localName ?localName .
43
+
30
44
  (
31
45
  { ?actualValue log:equalTo ?value }
32
46
  true
33
47
  {
34
- ("Expected status code " ?value " but got " ?actualValue)!string:concatenation^tuner:info .
48
+ ("Expected " ?localName " " ?value " but got " ?actualValue)!string:concatenation^tuner:info .
35
49
  true log:equalTo false .
36
50
  }
37
51
  ) log:ifThenElseIn ?SCOPE .