Skip to content

Commit

Permalink
Add independent testserver (#1672)
Browse files Browse the repository at this point in the history
* add independent testserver

* fix testserver

* move test function into util. Move nock config data into independent file
  • Loading branch information
jennyliang220 committed Nov 15, 2022
1 parent b8fce57 commit fe3ac99
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 254 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Expand Up @@ -69,6 +69,7 @@
"supersedable",
"Tantek",
"testtest",
"testserver",
"tocline",
"tocxref",
"ttml",
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -54,6 +54,7 @@
"prepare": "husky install",
"spelling": "cspell \"**/*\"",
"start": "node --use_strict app",
"testserver": "node test/lib/testserver.js",
"test": "NO_THROTTLE=true mocha"
},
"engines": {
Expand Down
90 changes: 90 additions & 0 deletions test/lib/nockData.js
@@ -0,0 +1,90 @@
export const nockData = {
versions: {
page: 1,
pages: 1,
_embedded: {
'version-history': [
{
uri: 'https://www.w3.org/TR/2022/WD-hr-time-3-20220117/',
},
{
uri: 'https://www.w3.org/TR/2021/WD-hr-time-3-20211201/',
},
{
uri: 'https://www.w3.org/TR/2021/WD-hr-time-3-20211012/',
},
],
},
},
groupNames: {
'i18n-core': 32113,
forms: 32219,
apa: 83907,
ag: 35422,
},
chartersData: {
32113: [
{
end: '2021-09-30',
'doc-licenses': [
{
uri: 'https://www.w3.org/Consortium/Legal/copyright-software',
name: 'W3C Software and Document License',
},
],
start: '2019-06-28',
'patent-policy':
'https://www.w3.org/Consortium/Patent-Policy-20170801/',
},
{
end: '2090-09-30',
'doc-licenses': [
{
uri: 'https://www.w3.org/Consortium/Legal/copyright-software',
name: 'W3C Software and Document License',
},
],
start: '2021-09-30',
'patent-policy':
'https://www.w3.org/Consortium/Patent-Policy-20200915/',
},
],
32219: {
end: '2012-03-31',
'doc-licenses': [],
start: '2010-05-17',
},
83907: {
end: '2090-07-31',
'doc-licenses': [
{
uri: 'https://www.w3.org/Consortium/Legal/copyright-documents',
name: 'W3C Document License',
},
{
uri: 'https://www.w3.org/Consortium/Legal/copyright-software',
name: 'W3C Software and Document License',
},
],
start: '2021-08-11',
'patent-policy':
'https://www.w3.org/Consortium/Patent-Policy-20200915/',
},
35422: {
end: '2090-10-31',
'doc-licenses': [
{
uri: 'https://www.w3.org/Consortium/Legal/copyright-documents',
name: 'W3C Document License',
},
{
uri: 'https://www.w3.org/Consortium/Legal/copyright-software',
name: 'W3C Software and Document License',
},
],
start: '2019-12-20',
'patent-policy':
'https://www.w3.org/Consortium/Patent-Policy-20170801/',
},
},
};
106 changes: 106 additions & 0 deletions test/lib/testserver.js
@@ -0,0 +1,106 @@
// start an server to host doc, response to sr.url requests
import express from 'express';
import pth, { dirname } from 'path';
import exphbs from 'express-handlebars';
import { fileURLToPath } from 'url';

const DEFAULT_PORT = 8001;
const PORT = process.env.PORT || DEFAULT_PORT;
const ENDPOINT = `http://localhost:${PORT}`;

// eslint-disable-next-line no-underscore-dangle
const __dirname = dirname(fileURLToPath(import.meta.url));

export const app = express();
app.use('/docs', express.static(pth.join(__dirname, 'docs')));

// use express-handlebars
app.engine(
'handlebars',
exphbs.engine({
defaultLayout: pth.join(__dirname, '../doc-views/layout/spec'),
layoutsDir: pth.join(__dirname, '../doc-views'),
partialsDir: pth.join(__dirname, '../doc-views/partials/'),
})
);
app.set('view engine', 'handlebars');
app.set('views', pth.join(__dirname, '../doc-views'));

function renderByConfig(req, res) {
const { rule, type } = req.query;
const suffix = req.params.track
? `${req.params.track}/${req.params.profile}`
: req.params.profile;

// get data for template from json (.js)
const path = pth.join(
__dirname,
`../doc-views/${req.params.docType}/${suffix}.js`
);

// eslint-disable-next-line node/no-unsupported-features/es-syntax
import(path).then(module => {
const data = module.default;

let finalData;
if (!type)
res.send(
'<h1>Error: please add the parameter "type" in the URL </h1>'
);
else if (type.startsWith('good')) {
finalData = data[type];
} else {
if (!rule)
res.send(
'<h1>Error: please add the parameter "rule" in the URL </h1>'
);

// for data causes error, make rule and the type of error specific.
finalData = data[rule][type];
}
res.render(pth.join(__dirname, '../doc-views/layout/spec'), finalData);
});
}

app.get('/doc-views/:docType/:track/:profile', renderByConfig);
app.get('/doc-views/:docType/:profile', renderByConfig);

// config single redirection
app.get('/docs/links/image/logo', (req, res) => {
res.redirect('/docs/links/image/logo.png');
});
// config single redirection to no where (404)
app.get('/docs/links/image/logo-fail', (req, res) => {
res.redirect('/docs/links/image/logo-fail.png');
});
// config multiple redirection
app.get('/docs/links/image/logo-redirection-1', (req, res) => {
res.redirect(301, '/docs/links/image/logo-redirection-2');
});
app.get('/docs/links/image/logo-redirection-2', (req, res) => {
res.redirect(307, '/docs/links/image/logo-redirection-3');
});
app.get('/docs/links/image/logo-redirection-3', (req, res) => {
res.redirect('/docs/links/image/logo.png');
});

// if run from `npm run testserver`, console sample links.
if (import.meta.url === `file://${process.argv[1]}`) {
app.listen(PORT, async () => {
console.log(
`===== Local test server running at ===== \n===== ${ENDPOINT} =====`
);
console.log(
`\nGood document link e.g. \n${ENDPOINT}/doc-views/TR/Registry/CRY?type=good`
);
console.log(
`\nBad document link e.g. \n${ENDPOINT}/doc-views/TR/Note/DNOTE-Echidna?rule=charter&type=noGroup`
);
console.log(
`\nBad document link for Member Submission e.g. \n${ENDPOINT}/doc-views/SUBM/MEM-SUBM?rule=reliability&type=hasUnreliableLinks`
);
});
} else {
// server run by mocha
console.log(`\nTestserver running for mocha. \nHosting ${ENDPOINT}`);
}
80 changes: 80 additions & 0 deletions test/lib/utils.js
@@ -0,0 +1,80 @@
import { lstatSync, readdirSync } from 'fs';

function listFilesOf(dir) {
const files = readdirSync(dir);

// ignore .DS_Store from Mac
const blocklist = ['.DS_Store', 'Base.js'];

return files.filter(v => !blocklist.find(b => v.includes(b)));
}

const flat = objs => objs.reduce((acc, cur) => ({ ...acc, ...cur }), {});

const buildProfileTestCases = async path => {
// eslint-disable-next-line node/no-unsupported-features/es-syntax
const { rules } = await import(path);
return rules;
};

const buildTrackTestCases = async path => {
if (lstatSync(path).isFile()) {
const profile = await buildProfileTestCases(path);
return profile;
}

const profiles = await Promise.all(
listFilesOf(path).map(async profile => ({
[profile]: await buildProfileTestCases(`${path}/${profile}`),
}))
);

return flat(profiles);
};

const buildDocTypeTestCases = async path => {
const tracks = await Promise.all(
listFilesOf(path).map(async track => ({
[track]: await buildTrackTestCases(`${path}/${track}`),
}))
);

return flat(tracks);
};

export const buildBadTestCases = async () => {
const base = `${process.cwd()}/test/data`;
const docTypes = await Promise.all(
listFilesOf(base)
.filter(v => lstatSync(`${base}/${v}`).isDirectory())
.map(async docType => ({
[docType]: await buildDocTypeTestCases(`${base}/${docType}`),
}))
);

return flat(docTypes);
};

/**
* Compare two arrays of "deliverer IDs" and check that they're equivalent.
*
* @param {Array} a1 - One array.
* @param {Array} a2 - The other array.
* @returns {Boolean} whether the two arrays contain exactly the same integers.
*/

export const equivalentArray = function (a1, a2) {
if (a1 && a2 && a1.length === a2.length) {
let found = 0;
for (let i = 0; i < a1.length; i += 1) {
for (let j = 0; j < a2.length && found === i; j += 1) {
if (a1[i] === a2[j]) {
found += 1;
}
}
}
return found === a1.length;
}

return false;
};

0 comments on commit fe3ac99

Please sign in to comment.