This commit is contained in:
parent
9686ccabc3
commit
25a7e29b20
10 changed files with 6795 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
|||
name: "Linting"
|
||||
name: "QS"
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -6,8 +6,8 @@ on:
|
|||
- main
|
||||
|
||||
jobs:
|
||||
javadoc:
|
||||
name: "Javadoc"
|
||||
qs:
|
||||
name: "QS"
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: "git.euph.dev/actions/runner-js-latest:latest"
|
||||
|
@ -16,3 +16,5 @@ jobs:
|
|||
uses: "https://git.euph.dev/actions/checkout@v3"
|
||||
- name: "Prettier"
|
||||
run: npm_config_yes=true npx prettier src/ types/ --check --log-level=error
|
||||
- name: "Run Tests"
|
||||
run: cd test && npm i --no-fund && npm run test
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.idea
|
||||
.vscode
|
||||
|
||||
test/node_modules
|
||||
test/package-lock.json
|
1
.prettierignore
Normal file
1
.prettierignore
Normal file
|
@ -0,0 +1 @@
|
|||
test/data
|
2
Makefile
2
Makefile
|
@ -1,2 +1,2 @@
|
|||
lint:
|
||||
@npx prettier src/ types/ --write
|
||||
@npx prettier src/ types/ test/ --write
|
6602
test/data/ccna1v7mod1-3/data.html
Normal file
6602
test/data/ccna1v7mod1-3/data.html
Normal file
File diff suppressed because it is too large
Load diff
60
test/data/ccna1v7mod1-3/test.json
Normal file
60
test/data/ccna1v7mod1-3/test.json
Normal file
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"name": "CCNA 1 v7 Modules 1 - 3 Basic Network Connectivity and Communications Exam Answers",
|
||||
"file": "data.html",
|
||||
"expected": [
|
||||
{
|
||||
"question": "What is an ISP?",
|
||||
"answers": [
|
||||
"It is an organization that enables individuals and businesses to connect to the Internet."
|
||||
]
|
||||
},
|
||||
{
|
||||
"question": "What type of network traffic requires QoS?",
|
||||
"answers": ["video conferencing"]
|
||||
},
|
||||
{
|
||||
"question": "Which interface allows remote management of a Layer 2 switch?",
|
||||
"answers": ["the switch virtual interface"]
|
||||
},
|
||||
{
|
||||
"question": "How is SSH different from Telnet?",
|
||||
"answers": [
|
||||
"SSH provides security to \nremote sessions by encrypting messages and using user authentication. \nTelnet is considered insecure and sends messages in plaintext."
|
||||
]
|
||||
},
|
||||
{
|
||||
"question": "What are three characteristics of an SVI? (Choose three.)",
|
||||
"answers": [
|
||||
"It is not associated with any physical interface on a switch.",
|
||||
"It provides a means to remotely manage a switch.",
|
||||
"It is associated with VLAN1 by default."
|
||||
]
|
||||
},
|
||||
{
|
||||
"question": "Which name is assigned to the transport layer PDU?",
|
||||
"answers": ["segment"]
|
||||
},
|
||||
{
|
||||
"question": "What process involves placing one PDU inside of another PDU?",
|
||||
"answers": ["encapsulation"]
|
||||
},
|
||||
{
|
||||
"question": "What is a characteristic of multicast messages?",
|
||||
"answers": ["They are sent to a select group of hosts."]
|
||||
},
|
||||
{
|
||||
"question": "Which statement is correct about network protocols?",
|
||||
"answers": [
|
||||
"They define how messages are exchanged between the source and the destination."
|
||||
]
|
||||
},
|
||||
{
|
||||
"question": "Why would a Layer 2 switch need an IP address?",
|
||||
"answers": ["to enable the switch to be managed remotely"]
|
||||
},
|
||||
{
|
||||
"question": "Which two devices are intermediary devices? (Choose two)",
|
||||
"answers": ["Router", "Switch"]
|
||||
}
|
||||
]
|
||||
}
|
32
test/fetch.test.js
Normal file
32
test/fetch.test.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
const fs = require('fs');
|
||||
const vm = require('vm');
|
||||
const { JSDOM } = require('jsdom');
|
||||
const { diff } = require('deep-diff');
|
||||
|
||||
const scriptContent = fs.readFileSync('../src/fetch.js', 'utf8');
|
||||
|
||||
/**
|
||||
* @param testData {string}
|
||||
* @param expectedData {Array<Answer>}
|
||||
* @returns {Promise<Array<Answer>>}
|
||||
*/
|
||||
module.exports = async function executeFetchTest(testData, expectedData) {
|
||||
const sandbox = {
|
||||
window: {},
|
||||
DOMParser: new JSDOM().window.DOMParser,
|
||||
console: console
|
||||
};
|
||||
vm.createContext(sandbox);
|
||||
vm.runInContext(scriptContent, sandbox);
|
||||
const { parseAnswers } = sandbox;
|
||||
return new Promise((resolve, reject) => {
|
||||
parseAnswers({ responseText: testData }, results => {
|
||||
const { diff } = require('deep-diff');
|
||||
const changes = diff({ data: results }, { data: expectedData });
|
||||
if (changes !== undefined) {
|
||||
reject(changes);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
7
test/jsconfig.json
Normal file
7
test/jsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"checkJs": true,
|
||||
"module": "commonjs",
|
||||
"target": "es6"
|
||||
}
|
||||
}
|
11
test/package.json
Normal file
11
test/package.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"scripts": {
|
||||
"test": "node test.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^4",
|
||||
"deep-diff": "^1.0.2",
|
||||
"jsdom": "^24.0.0",
|
||||
"vm": "^0.1.0"
|
||||
}
|
||||
}
|
70
test/test.js
Normal file
70
test/test.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const executeFetchTest = require('./fetch.test');
|
||||
|
||||
const ERROR_MESSAGE = chalk.red('[Error]');
|
||||
const TEST_MESSAGE = chalk.blue('[Test]');
|
||||
const SUCCESS_MESSAGE = chalk.green('Success:');
|
||||
const FAILED_MESSAGE = chalk.red('Failed:');
|
||||
|
||||
(async () => {
|
||||
let fail = 0;
|
||||
const dataDirectory = path.join(__dirname, 'data');
|
||||
const directories = fs.readdirSync(dataDirectory);
|
||||
const promises = directories.map(directory => {
|
||||
const testDataDirectory = path.join(dataDirectory, directory);
|
||||
|
||||
if (!fs.lstatSync(testDataDirectory).isDirectory()) {
|
||||
console.error(
|
||||
ERROR_MESSAGE,
|
||||
'Test data directory is not a directory:',
|
||||
testDataDirectory
|
||||
);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const testJSONFilePath = path.join(testDataDirectory, 'test.json');
|
||||
if (!fs.existsSync(testJSONFilePath)) {
|
||||
console.error(
|
||||
ERROR_MESSAGE,
|
||||
'Test config file missing:',
|
||||
testJSONFilePath
|
||||
);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const data = fs.readFileSync(testJSONFilePath, 'utf8');
|
||||
try {
|
||||
const jsonData = JSON.parse(data);
|
||||
const testData = fs.readFileSync(
|
||||
path.join(testDataDirectory, jsonData.file),
|
||||
'utf8'
|
||||
);
|
||||
|
||||
return executeFetchTest(testData, jsonData.expected)
|
||||
.then(() => {
|
||||
console.log(TEST_MESSAGE, SUCCESS_MESSAGE, jsonData.name);
|
||||
})
|
||||
.catch(error => {
|
||||
fail++;
|
||||
console.error(
|
||||
TEST_MESSAGE,
|
||||
FAILED_MESSAGE,
|
||||
jsonData.name,
|
||||
error
|
||||
);
|
||||
});
|
||||
} catch (parseErr) {
|
||||
console.error(ERROR_MESSAGE, 'Parsing test config file:', parseErr);
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
if (fail > 0) {
|
||||
process.exitCode = 1;
|
||||
console.error(`${ERROR_MESSAGE} Failed Tests: ${fail}`);
|
||||
}
|
||||
})();
|
Loading…
Reference in a new issue