+
+
Siemens API Linter Report
+
+
+
+
+
+
+
Total Rules Count: {{this.enabledCount}}
+
+
+
+
+
+
+ Severity
+ Problems
+
+
+
+
+ Errors
+ {{this.errorCount}}
+
+
+ Warnings
+ {{this.warnCount}}
+
+
+ Info
+ {{this.infoCount}}
+
+
+ Hints
+ {{this.hintCount}}
+
+
+
+
+
+
+
+
+
+
+
Detailed report
+
+
+
+
+
+
+ {{#each this.data}}
+
+
+ {{#if hasDetails}}
+
+
+
+
+ {{/if}}
+
+ {{ruleName}}
+ {{ruleDescription}}
+ {{#if hasDetails}}
+ {{message}}
+ {{else}}
+ {{message}}
+ {{/if}}
+
+
+
+ {{#if hasDetails}}
+
+
+
+ #
+ Line
+ Severity
+ Path
+ message
+
+
+
+ {{#each details}}
+
+ {{inc @index}}
+ {{line}}
+ {{severity}}
+ {{path}}
+ {{message}}
+
+ {{/each}}
+
+
+ {{/if}}
+
+
+
+ {{/each}}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api-linter/test/api-commonops.test.js b/api-linter/test/api-commonops.test.js
new file mode 100644
index 0000000..6f148eb
--- /dev/null
+++ b/api-linter/test/api-commonops.test.js
@@ -0,0 +1,123 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyErrors, assertOnlyInfos } = require("./base.js")
+
+const path = 'commonops/';
+const rulesetPath = "test/testdata/commonops/.spectral.yml";
+
+test('A Successful fetch of individual resources MUST return the status code 200', async () => {
+ const specFilePath = getSpecFilePath(path, "800-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[800.1]");
+ //Problem in line:29
+ assertOnlyErrors(results);
+ });
+})
+
+test('A successful fetch of resource collection request MUST return a 2xx status code', async () => {
+ const specFilePath = getSpecFilePath(path, "800-2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[800.2]");
+ //Problem in line:37
+ assertOnlyErrors(results);
+ });
+})
+
+test('An API Provider MUST support fetching resource data for provided links', async () => {
+ const specFilePath = getSpecFilePath(path, "800-4.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[800.4]");
+ //Problem in line:50
+ assertOnlyErrors(results);
+ });
+})
+
+test('The POST request MUST include a single resource object as primary data', async () => {
+ const specFilePath = getSpecFilePath(path, "801.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[801]");
+ //Problem in line:45-47
+ assertOnlyErrors(results);
+ });
+})
+
+test('API MUST respond to successful POST creation request with 2xx success status code', async () => {
+ const specFilePath = getSpecFilePath(path, "801-4.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[801.4]");
+ //Problem in line:34
+ assertOnlyErrors(results);
+ });
+})
+
+test('API MUST respond to successful PATCH update request with 2xx success status code', async () => {
+ const specFilePath = getSpecFilePath(path, "802-6.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[802.6]");
+ //Problem in line:42
+ assertOnlyErrors(results);
+ });
+})
+
+test('API MUST respond to successful PUT update request with 2xx success status code', async () => {
+ const specFilePath = getSpecFilePath(path, "803-2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[803.2]");
+ //Problem in line:42
+ assertOnlyErrors(results);
+ });
+})
+
+test('API MUST respond to successful DELETE request with 2xx success status code', async () => {
+ const specFilePath = getSpecFilePath(path, "804-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[804.1]");
+ //Problem in line:37
+ assertOnlyErrors(results);
+ });
+})
+
+test('The API consumer MAY use conditional header information to solve concurrent update requests', async () => {
+ const specFilePath = getSpecFilePath(path, "803-6.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[803.6]");
+ //Problem in line:37-40
+ assertOnlyInfos(results);
+ });
+})
+
diff --git a/api-linter/test/api-errors-refs.test.js b/api-linter/test/api-errors-refs.test.js
new file mode 100644
index 0000000..db05af4
--- /dev/null
+++ b/api-linter/test/api-errors-refs.test.js
@@ -0,0 +1,42 @@
+// test/api-errors-refs.test.js
+const fs = require('fs');
+const { Document } = require('@stoplight/spectral-core');
+const Parsers = require('@stoplight/spectral-parsers');
+
+// 👇 RE-ADD setupSpectral here
+const { setupSpectral } =
+ require('@jamietanna/spectral-test-harness');
+
+const { resultsForSeverity } = require('./base.js');
+const { resolver } = require('@stoplight/spectral-ref-resolver');
+const path = require('path');
+
+const rulesetPath = 'test/testdata/refs/.spectral.yml';
+const specFilePath = path.join(__dirname, 'testdata/refs', '300.yml'); // ABSOLUTE
+
+test('API MUST use official HTTP status codes as intended', async () => {
+ // ───────────── arrange ─────────────
+ /* ── Spectral with resolver ── */
+ const spectral = await setupSpectral(rulesetPath, { resolver });
+
+ /* ── Document with correct source (real path!) ── */
+ const raw = fs.readFileSync(specFilePath, 'utf8');
+ const document = new Document(raw, Parsers.Yaml, specFilePath);
+ // … but give it the real filename so $ref resolution works
+ document.source = specFilePath;
+
+ // ───────────── act ─────────────
+ const results = await spectral.run(
+ document,
+ { resolve: { external: true } }
+ );
+
+ // ───────────── assert ─────────────
+ const errors = resultsForSeverity(results, 'Error');
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe('Siemens-API-[300]');
+ //Problem in line:35-40
+ const warnings = resultsForSeverity(results, 'Warning');
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe('Siemens-API-[301]');
+});
diff --git a/api-linter/test/api-errors.test.js b/api-linter/test/api-errors.test.js
new file mode 100644
index 0000000..4cf0453
--- /dev/null
+++ b/api-linter/test/api-errors.test.js
@@ -0,0 +1,85 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyWarnings, assertOnlyInfos } = require("./base.js")
+
+const path = 'error/';
+const rulesetPath = "test/testdata/error/.spectral.yml";
+
+test('API MUST use official HTTP status codes as intended', async () => {
+ const specFilePath = getSpecFilePath(path, "300.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[300]");
+ //Problem in line:35-40
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[301]");
+ });
+})
+
+test('SHOULD only use most common HTTP status codes', async () => {
+ const specFilePath = getSpecFilePath(path, "301.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ //Problem in line:35-40
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[301]");
+ assertOnlyWarnings(results);
+ });
+})
+
+ test('SHOULD use the most specific HTTP status code when returning errors', async () => {
+ const specFilePath = getSpecFilePath(path, "302.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ //Problem in line:130
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[302]");
+ assertOnlyWarnings(results);
+ });
+ })
+
+ test('Error object SHOULD be represented according to the defined structure fields', async () => {
+ const specFilePath = getSpecFilePath(path, "305.1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ //Problem in line:110
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[305]-1");
+ assertOnlyWarnings(results);
+ });
+ })
+
+ test('The error links resource object MAY contain the members: about, type', async () => {
+ const specFilePath = getSpecFilePath(path, "305.2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ //Problem in line:114-117
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[305]-2");
+ assertOnlyInfos(results)
+ });
+ })
+
+ test('The source object SHOULD include one of the members or be omitted: pointer, parameter, header', async () => {
+ const specFilePath = getSpecFilePath(path, "305.3.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ //Problem in line:114-117
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[305]-3");
+ assertOnlyWarnings(results);
+ });
+ })
\ No newline at end of file
diff --git a/api-linter/test/api-filtering.test.js b/api-linter/test/api-filtering.test.js
new file mode 100644
index 0000000..25f01ce
--- /dev/null
+++ b/api-linter/test/api-filtering.test.js
@@ -0,0 +1,30 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyInfos, assertOnlyHints } = require("./base.js")
+
+const path = 'filtering/';
+const rulesetPath = "test/testdata/filtering/.spectral.yml";
+
+test('An API provider MAY NOT support more than 4 parameters at once for selecting resources', async () => {
+ const specFilePath = getSpecFilePath(path, "400.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const hints = resultsForSeverity(results, "Hint");
+ expect(hints).toHaveLength(2);
+ expect(hints[0].code).toBe("Siemens-API-[400]");
+ expect(hints[1].code).toBe("Siemens-API-[401]");
+ //Problem in line:29-62
+ assertOnlyHints(results);
+ });
+})
+
+test('The query parameter filter SHOULD be used to filter or query data', async () => {
+ const specFilePath = getSpecFilePath(path, "401.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(0);
+ assertOnlyInfos(results);
+ });
+})
\ No newline at end of file
diff --git a/api-linter/test/api-linter-cli.test.js b/api-linter/test/api-linter-cli.test.js
new file mode 100644
index 0000000..1fc1477
--- /dev/null
+++ b/api-linter/test/api-linter-cli.test.js
@@ -0,0 +1,60 @@
+const path = require('path');
+const fs = require('fs');
+const { spawnSync } = require('child_process');
+
+/* ─────────── paths used by both tests ─────────── */
+const cli = path.join(__dirname, '..', 'src', 'index.js');
+const ruleset = path.join(__dirname, 'testdata', 'refs', '.spectral.yml');
+const spec = path.join(__dirname, 'testdata', 'refs', '300.yml');
+
+/* handy wrapper to invoke the CLI */
+function runLinter({ resolveFlag, reportFile }) {
+ const args = [
+ cli,
+ '--specPath', spec,
+ '--rulesetPath', ruleset,
+ '--failSeverity','error',
+ '--outputFilename', reportFile
+ ];
+ if (resolveFlag) args.push('--resolve');
+
+ return spawnSync('node', args, { encoding: 'utf8' });
+}
+
+describe('api-linter CLI external $ref behaviour', () => {
+ const reportWith = path.join(__dirname, 'tmp-report-resolve.html');
+ const reportWithout = path.join(__dirname, 'tmp-report-no-resolve.html');
+
+ /* clean-up generated HTML files after the suite finished */
+ afterAll(() => {
+ [reportWith, reportWithout].forEach(f => {
+ if (fs.existsSync(f)) fs.unlinkSync(f);
+ });
+ });
+
+ test('with --resolve follows external refs (no invalid-ref)', () => {
+ const { status, stdout } = runLinter({
+ resolveFlag: true,
+ reportFile: reportWith
+ });
+
+ /* exit-code still 1 because the real rule fires */
+ expect(status).toBe(1);
+ expect(stdout).toMatch(/Siemens-API-\[300]/); // rule present
+ expect(stdout).not.toMatch(/invalid-ref/); // resolver worked
+ expect(fs.existsSync(reportWith)).toBe(true); // report created
+ });
+
+ test('without --resolve produces invalid-ref error', () => {
+ const { status, stdout } = runLinter({
+ resolveFlag: false,
+ reportFile: reportWithout
+ });
+
+ expect(status).toBe(1);
+ expect(stdout).toMatch(/Siemens-API-\[300]/); // rule present
+ expect(stdout).toMatch(/Siemens-API-\[301]/); // rule present
+ expect(stdout).not.toMatch(/invalid-ref/); // Spectral never tried to search for external references
+ expect(fs.existsSync(reportWithout)).toBe(true);
+ });
+});
\ No newline at end of file
diff --git a/api-linter/test/api-mediatype.test.js b/api-linter/test/api-mediatype.test.js
new file mode 100644
index 0000000..262c5df
--- /dev/null
+++ b/api-linter/test/api-mediatype.test.js
@@ -0,0 +1,114 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyErrors, assertOnlyWarnings, assertOnlyInfos } = require("./base.js")
+
+const path = 'mediatype/';
+const rulesetPath = "test/testdata/mediatype/.spectral.yml";
+
+test('Siemens Xcelerator recommends the media type application/json for exchanging data.', async () => {
+ const specFilePath = getSpecFilePath(path, "100.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[100]");
+ //Problem in line:32
+ assertOnlyInfos(results);
+ });
+})
+
+test('The root of every document SHOULD contain a JSON object', async () => {
+ const specFilePath = getSpecFilePath(path, "101-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[101.1]");
+ //Problem in line:38
+ assertOnlyWarnings(results);
+ });
+})
+
+test('A response document SHOULD contain at least one of the following:data,error,meta,links.', async () => {
+ const specFilePath = getSpecFilePath(path, "101-2.1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[101.2]-1");
+ //Problem in line:40-42, properties should contain at least one of data,error,meta,links
+ assertOnlyWarnings(results);
+ });
+})
+
+test('A request document SHOULD contain at least data', async () => {
+ const specFilePath = getSpecFilePath(path, "101-2.2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[101.2]-2");
+ //Problem in line:45-47, properties should contain at least data
+ assertOnlyWarnings(results);
+ });
+})
+
+test('The data type MUST be compliant with the types defined', async () => {
+ const specFilePath = getSpecFilePath(path, "101-4-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[101.4.1]");
+ //Problem in line:87, should be one of boolean|object|array|integer|number|string
+ assertOnlyErrors(results);
+ });
+})
+
+test('A meta object SHOULD be used to represent meta information as a JSON object', async () => {
+ const specFilePath = getSpecFilePath(path, "101-7-2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[101.7.2]");
+ //Problem in line:77, should be type: object
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[101.7]");
+ });
+})
+
+test('Field names SHOULD use lower camel case', async () => {
+ const specFilePath = getSpecFilePath(path, "101-8.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[101.8]");
+ //Problem in line:68, should be addressDetail
+ assertOnlyWarnings(results);
+ });
+})
+
+test('Resource names SHOULD be in lowercase with hyphen', async () => {
+ const specFilePath = getSpecFilePath(path, "101-9.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[101.9]");
+ //Problem in line:20, should be room-details
+ assertOnlyWarnings(results);
+ });
+})
+
+
+
diff --git a/api-linter/test/api-pagination.test.js b/api-linter/test/api-pagination.test.js
new file mode 100644
index 0000000..5d9dfa5
--- /dev/null
+++ b/api-linter/test/api-pagination.test.js
@@ -0,0 +1,102 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyInfos, assertOnlyHints } = require("./base.js")
+
+const path = 'pagination/';
+const rulesetPath = "test/testdata/pagination/.spectral.yml";
+
+test('A server MAY provide links to traverse a paginated data set', async () => {
+ const specFilePath = getSpecFilePath(path, "600.1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[600]-1");
+ assertOnlyInfos(results);
+ });
+ })
+
+test('Pagination links SHOULD appear in the top-level links object.', async () => {
+ const specFilePath = getSpecFilePath(path, "600.2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[600]-2");
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[600]-1");
+ });
+})
+
+test('Naming convention MUST be used for pagination keys.', async () => {
+ const specFilePath = getSpecFilePath(path, "600.3.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const hints = resultsForSeverity(results, "Hint");
+ expect(hints).toHaveLength(1);
+ expect(hints[0].code).toBe("Siemens-API-[600]-3");
+ assertOnlyHints(results);
+ });
+})
+
+test('Pagination SHOULD be implemented using query parameters.', async () => {
+ const specFilePath = getSpecFilePath(path, "601.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const warnings = resultsForSeverity(results, "Warning");
+ expect(warnings).toHaveLength(1);
+ expect(warnings[0].code).toBe("Siemens-API-[601]");
+ });
+})
+
+test('Server MAY provide pagination meta information to the client [601.1.1].', async () => {
+ const specFilePath = getSpecFilePath(path, "601-1-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[601.1.1]");
+ assertOnlyInfos(results);
+ });
+})
+
+test('Server MAY provide pagination meta information to the client [601.2.1].', async () => {
+ const specFilePath = getSpecFilePath(path, "601-2-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[601.2.1]");
+ assertOnlyInfos(results);
+ });
+})
+
+test('Server MAY provide pagination meta information to the client [601.3.1].', async () => {
+ const specFilePath = getSpecFilePath(path, "601-3-1.1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[601.3.1]-1");
+ assertOnlyInfos(results);
+ });
+})
+
+test('Server MAY provide pagination meta information to the client [601.3.1].', async () => {
+ const specFilePath = getSpecFilePath(path, "601-3-1.2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[601.3.1]-2");
+ assertOnlyInfos(results);
+ });
+})
\ No newline at end of file
diff --git a/api-linter/test/api-security.test.js b/api-linter/test/api-security.test.js
new file mode 100644
index 0000000..44a9ee5
--- /dev/null
+++ b/api-linter/test/api-security.test.js
@@ -0,0 +1,49 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyErrors } = require("./base.js")
+
+const path = 'security/';
+const rulesetPath = "test/testdata/security/.spectral.yml";
+
+test('No security problem test 1', async () => {
+ global.apiSecurity = 'y';
+ const specFilePath = getSpecFilePath(path, "valid.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ expect(results).toHaveLength(0);
+ });
+})
+
+test('No security problem test 2', async () => {
+ global.apiSecurity = 'n';
+ const specFilePath = getSpecFilePath(path, "invalid.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ expect(results).toHaveLength(0);
+ });
+})
+
+test('No security problem test 3', async () => {
+ global.apiSecurity = 'n';
+ const specFilePath = getSpecFilePath(path, "invalid.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ expect(results).toHaveLength(0);
+ });
+})
+
+test('Has security problem test', async () => {
+ global.apiSecurity = 'y';
+ const specFilePath = getSpecFilePath(path, "invalid.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ expect(results).toHaveLength(1);
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-Security");
+ assertOnlyErrors(results);
+ });
+})
\ No newline at end of file
diff --git a/api-linter/test/api-sparse-fieldsets.test.js b/api-linter/test/api-sparse-fieldsets.test.js
new file mode 100644
index 0000000..fc5c0fa
--- /dev/null
+++ b/api-linter/test/api-sparse-fieldsets.test.js
@@ -0,0 +1,17 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyInfos } = require("./base.js")
+
+const path = 'fields/';
+const rulesetPath = "test/testdata/fields/.spectral.yml";
+
+test('API MAY provide projection of fieldset in response', async () => {
+ const specFilePath = getSpecFilePath(path, "500.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const infos = resultsForSeverity(results, "Information");
+ expect(infos).toHaveLength(1);
+ expect(infos[0].code).toBe("Siemens-API-[500]");
+ assertOnlyInfos(results);
+ });
+ })
diff --git a/api-linter/test/api-versioning.test.js b/api-linter/test/api-versioning.test.js
new file mode 100644
index 0000000..002ecea
--- /dev/null
+++ b/api-linter/test/api-versioning.test.js
@@ -0,0 +1,61 @@
+const { retrieveDocument, setupSpectral} = require('@jamietanna/spectral-test-harness')
+const {resultsForSeverity, getSpecFilePath, assertOnlyErrors, assertOnlyWarnings } = require("./base.js")
+
+const path = 'versioning/';
+const rulesetPath = "test/testdata/versioning/.spectral.yml";
+
+test('Semantic versioning MUST be used to version individual APIs', async () => {
+ global.apiVersioning = 'url';
+ const specFilePath = getSpecFilePath(path, "semantic-versioning.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Semantic-Versioning-[2.0.0]");
+ //Problem in line:35-40
+ assertOnlyErrors(results);
+ });
+})
+
+test('The Major version number MUST be specified in the URI as a path segment', async () => {
+ global.apiVersioning = 'url';
+ const specFilePath = getSpecFilePath(path, "200-1.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[200.1]");
+ //Problem in line:13
+ assertOnlyErrors(results);
+ });
+})
+
+test('A request HTTP header e.g., Api-Version MUST be supported to allow client to specify the version.', async () => {
+ global.apiVersioning = 'header';
+ const specFilePath = getSpecFilePath(path, "200-2.yml");
+ const spectral = await setupSpectral(rulesetPath);
+ const document = retrieveDocument(specFilePath);
+ spectral.run(document).then(results => {
+ const errors = resultsForSeverity(results, "Error");
+ expect(errors).toHaveLength(1);
+ expect(errors[0].code).toBe("Siemens-API-[200.2]");
+ //Problem in line:29
+ assertOnlyErrors(results);
+ });
+})
+
+test("A header with full semantic version value SHOULD be returned in the response with 'Api-Version: