Skip to content

Commit

Permalink
Add tests for valdate options functions
Browse files Browse the repository at this point in the history
  • Loading branch information
AhmedElbohoty committed Sep 4, 2024
2 parents e277709 + ab16b15 commit 9b6e8b4
Show file tree
Hide file tree
Showing 16 changed files with 297 additions and 149 deletions.
2 changes: 1 addition & 1 deletion .livecodes/js-esm.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"script": {
"language": "javascript",
"content": "import { race } from \"racing-bars\";\n\n/** @type {import('racing-bars').Options} */\nconst options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population in 60 Years\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n};\n\nrace(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n"
"content": "import { race } from \"racing-bars\";\n\n/** @type {import('racing-bars').Options} */\nconst options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n};\n\nrace(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n"
},
"customSettings": {
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion .livecodes/js-umd.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"script": {
"language": "javascript",
"content": "const options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population in 60 Years\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n};\n\nracingBars.race(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n"
"content": "const options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n};\n\nracingBars.race(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n"
},
"customSettings": {
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion .livecodes/react.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
"script": {
"language": "jsx",
"content": "import RacingBars from \"racing-bars/react\";\n\nexport default function App() {\n /** @type {import('racing-bars').Options} */\n const options = {\n dataUrl: \"{{LC::TO_URL(./data/population.csv)}}\",\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population in 60 Years\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n };\n\n return <RacingBars className=\"race\" {...options}>Loading...</RacingBars>;\n}\n"
"content": "import RacingBars from \"racing-bars/react\";\n\nexport default function App() {\n /** @type {import('racing-bars').Options} */\n const options = {\n dataUrl: \"{{LC::TO_URL(./data/population.csv)}}\",\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n };\n\n return <RacingBars className=\"race\" {...options}>Loading...</RacingBars>;\n}\n"
},
"customSettings": {
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion .livecodes/svelte.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"activeEditor": "script",
"script": {
"language": "svelte",
"content": "<script>\n import { onMount } from \"svelte\";\n import { race } from \"racing-bars\";\n\n const options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population in 60 Years\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n };\n\n onMount(() => {\n race(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n });\n</script>\n\n<div id=\"race\">Loading...</div>\n\n<style>\n #race {\n height: 80vh;\n }\n</style>\n"
"content": "<script>\n import { onMount } from \"svelte\";\n import { race } from \"racing-bars\";\n\n const options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n };\n\n onMount(() => {\n race(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n });\n</script>\n\n<div id=\"race\">Loading...</div>\n\n<style>\n #race {\n height: 80vh;\n }\n</style>\n"
},
"customSettings": {
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion .livecodes/ts.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"script": {
"language": "typescript",
"content": "import { race, type Options } from \"racing-bars\";\n\nconst options: Options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population in 60 Years\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n};\n\nrace(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n"
"content": "import { race, type Options } from \"racing-bars\";\n\nconst options: Options = {\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n};\n\nrace(\"{{LC::TO_URL(./data/population.csv)}}\", \"#race\", options);\n"
},
"customSettings": {
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion .livecodes/vue.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"activeEditor": "script",
"script": {
"language": "vue",
"content": "<script setup>\n import RacingBars from \"racing-bars/vue\";\n\n const options = {\n dataUrl: \"{{LC::TO_URL(./data/population.csv)}}\",\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population in 60 Years\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n };\n</script>\n\n<template>\n <RacingBars class=\"race\" v-bind=\"options\">Loading...</RacingBars>\n</template>\n\n<style scoped>\n .race {\n height: 80vh;\n }\n</style>\n"
"content": "<script setup>\n import RacingBars from \"racing-bars/vue\";\n\n const options = {\n dataUrl: \"{{LC::TO_URL(./data/population.csv)}}\",\n dataTransform: (data) =>\n data.map((d) => ({\n ...d,\n icon: `https://flagsapi.com/${d.code}/flat/64.png`,\n })),\n title: \"World Population\",\n subTitle: \"Country Population in millions\",\n caption: \"Source: World Bank\",\n dateCounter: \"YYYY\",\n showIcons: true,\n labelsPosition: \"outside\",\n };\n</script>\n\n<template>\n <RacingBars class=\"race\" v-bind=\"options\">Loading...</RacingBars>\n</template>\n\n<style scoped>\n .race {\n height: 80vh;\n }\n</style>\n"
},
"customSettings": {
"imports": {
Expand Down
192 changes: 128 additions & 64 deletions scripts/start-release.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,53 +10,91 @@ const pkgPath = '../src/package.lib.json';
const changelogPath = '../CHANGELOG.md';

const pkg = require(pkgPath);
const originalVersion = pkg.version;
const stringify = (obj) => JSON.stringify(obj, null, 2) + '\n';

const gitBranch = execSync('git rev-parse --abbrev-ref HEAD').toString().replace(/\n/g, '');
if (gitBranch !== 'develop') {
console.log('Can only prepare a release from branch: develop');
process.exit(1);
}
const confirmCancel = async (continueFn) => {
if (await confirm({ message: 'Do you want to cancel release and discard all changes?' })) {
execSync(`git reset --hard`);
console.log('Release cancelled!');
process.exit(1);
}
return continueFn();
};

const gitStatus = execSync('git status -s').toString().replace(/\n/g, '').trim();
if (gitStatus) {
console.log('Please commit changes before starting a release.');
process.exit(1);
}
const checkIsDevelop = () => {
const gitBranch = execSync('git rev-parse --abbrev-ref HEAD').toString().replace(/\n/g, '');
if (gitBranch !== 'develop') {
console.log('Can only start a release from branch: develop');
process.exit(1);
}
};

const getVersion = () =>
input({
message: 'Please specify the new version:',
validate(value) {
const parts = value.split('.');
if (parts.length !== 3) return false;
for (const part of parts) {
if (isNaN(Number(part))) return false;
}
return true;
},
});
const checkIsClean = () => {
const gitStatus = execSync('git status -s').toString().replace(/\n/g, '').trim();
if (gitStatus) {
console.log('Please commit changes before starting a release.');
process.exit(1);
}
};

const performChecks = async () => {
checkIsDevelop();
checkIsClean();
};

const bumpVersion = (libBump) => {
if (!libBump) return;
let [major, minor, patch] = pkg.version.split('.');
if (libBump === 'major') {
const bumpVersion = (oldVersion, bump) => {
if (!bump) return;
let [major, minor, patch] = oldVersion.split('.');
if (bump === 'major') {
major = String(Number(major) + 1);
minor = '0';
patch = '0';
}
if (libBump === 'minor') {
if (bump === 'minor') {
minor = String(Number(minor) + 1);
patch = '0';
}
if (libBump === 'patch') {
if (bump === 'patch') {
patch = String(Number(patch) + 1);
}
return `${major}.${minor}.${patch}`;
};

const getBump = () =>
select({
message: 'Library version upgrade:',
const specifyVersion = () =>
input({
message: 'Please specify the new version:',
validate(value) {
const version = value.startsWith('v') ? value.slice(1) : value;
const parts = version.split('.');
if (parts.length !== 3) return false;
for (const part of parts) {
if (isNaN(Number(part))) return false;
}
const originalVersionParts = originalVersion.split('.');
if (Number(parts[0]) > Number(originalVersionParts[0])) return true;
if (Number(parts[1]) > Number(originalVersionParts[1])) return true;
if (Number(parts[2]) > Number(originalVersionParts[2])) return true;
return false;
},
});

const getBump = async (releaseNotes) => {
const suggestedBump = releaseNotes.includes('### BREAKING CHANGES')
? 'major'
: releaseNotes.includes('### Features')
? 'minor'
: 'patch';
const hint =
suggestedBump === 'major'
? ' (has breaking changes!)'
: suggestedBump === 'minor'
? ' (includes new feature(s))'
: '';

const bump = await select({
message: `Library version upgrade:${hint}`,
default: suggestedBump,
choices: [
{
name: 'Major',
Expand All @@ -74,58 +112,84 @@ const getBump = () =>
name: 'Specify version',
value: 'specify',
},
{
name: 'Cancel',
value: 'cancel',
},
],
});

const stringify = (obj) => JSON.stringify(obj, null, 2) + '\n';

const cancelRelease = async () => {
if (await confirm({ message: 'Cancelling release. Do you want to discard all changes?' })) {
execSync(`git reset --hard`);
if (bump === 'cancel') {
return confirmCancel(() => getBump(releaseNotes));
}
console.log('Release cancelled!');
process.exit(1);
return bump;
};

(async () => {
const libBump = await getBump();
pkg.version = libBump === 'specify' ? await getVersion() : bumpVersion(libBump);
const version = 'v' + pkg.version;
if (!(await confirm({ message: `Creating version: ${version}\nProceed?` }))) {
await cancelRelease();
const changeVersion = async (releaseNotes) => {
const bump = await getBump(releaseNotes);
const selectedVersion =
bump === 'specify' ? await specifyVersion() : bumpVersion(originalVersion, bump);
const version = selectedVersion?.startsWith('v') ? selectedVersion.slice(1) : selectedVersion;
const versionName = 'v' + version;
pkg.version = version;
if (!(await confirm({ message: `Creating version: ${versionName}\nProceed?` }))) {
return confirmCancel(async () => changeVersion(releaseNotes));
}
fs.writeFileSync(new URL(pkgPath, import.meta.url), stringify(pkg), 'utf8');
return releaseNotes;
};

const changelog = fs.readFileSync(new URL(changelogPath, import.meta.url), 'utf8');
const changelogSeparator = '\n---';
const [changelogHeader, ...prevLogs] = changelog.split(changelogSeparator);
const streamToString = (stream) => {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
stream.on('error', (err) => reject(err));
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
});
};

const releaseChangelog = await streamToString(
const getReleaseNotes = async () =>
streamToString(
conventionalChangelog({
preset: 'angular',
}),
).then((str) => {
return '\n\n#' + str.replace('[0.0.0]', `[${version}]`).replace('v0.0.0', `${version}`);
});
);

const writeChangelog = async (releaseNotes) => {
const version = 'v' + pkg.version;
const changelog = fs.readFileSync(new URL(changelogPath, import.meta.url), 'utf8');
const changelogSeparator = '\n---';
const [changelogHeader, ...prevLogs] = changelog.split(changelogSeparator);
const releaseChangelog =
'\n\n#' + releaseNotes.replace('[0.0.0]', `[${version}]`).replace('v0.0.0', `${version}`);
const newChangelog = [changelogHeader, releaseChangelog, ...prevLogs].join(changelogSeparator);
fs.writeFileSync(new URL(changelogPath, import.meta.url), newChangelog, 'utf8');

if (!(await confirm({ message: `Change log added to ./CHANGELOG.md\nProceed?` }))) {
await cancelRelease();
}
const waitForApproval = async () => {
if (!(await confirm({ message: `Change log added to ./CHANGELOG.md\nProceed?` }))) {
return confirmCancel(waitForApproval);
}
return version;
};
return waitForApproval();
};

const pushReleaseBranch = (version) => {
if (!version) {
console.log('Invalid version. Aborting.');
process.exit(1);
}
const branchName = 'releases/' + version;
execSync(`git checkout -b ${branchName}`);
execSync(`git add -A && git commit -m "release: ${version}"`);
execSync(`git push -u origin ${branchName}`);
})();
};

function streamToString(stream) {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
stream.on('error', (err) => reject(err));
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
});
}
const run = async () => {
performChecks()
.then(getReleaseNotes)
.then(changeVersion)
.then(writeChangelog)
.then(pushReleaseBranch);
};

run();
44 changes: 31 additions & 13 deletions src/lib/css/styles.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
__selector__ {
--base-font-size: max(1vw, 12px);
--text-font-size: calc(var(--base-font-size) * 1.2);
--title-font-size: calc(var(--base-font-size) * 2);
--caption-font-size: calc(var(--base-font-size) * 1.5);
--counter-font-size: calc(var(--base-font-size) * 4);
--controls-font-size: calc(var(--base-font-size) * 1.5);
}

__selector__ text {
font-family:
Open Sans,
sans-serif;
font-size: 16px;
font-size: var(--text-font-size);
}

__selector__ text.title {
font-size: 24px;
font-size: var(--title-font-size);
font-weight: 500;
}

Expand All @@ -15,7 +24,7 @@ __selector__ text.subTitle {
}

__selector__ text.caption {
font-size: 24px;
font-size: var(--caption-font-size);
font-weight: 400;
}

Expand All @@ -36,7 +45,7 @@ __selector__ text.valueLabel {
}

__selector__ text.dateCounterText {
font-size: 64px;
font-size: var(--counter-font-size);
font-weight: 700;
}

Expand All @@ -63,22 +72,29 @@ __selector__ .controls {

__selector__ .controls div,
__selector__ .overlay div {
align-items: center;
border-radius: 5px;
border-radius: 5px;
border-radius: 5px;
cursor: pointer;
font-size: 24px;
font-weight: 700;
height: 38px;
display: flex;
justify-content: center;
margin: 5px;
text-align: center;
width: 38px;
}

__selector__ .controls div {
height: 10vw;
max-height: 32px;
max-width: 32px;
width: 10vw;
}

__selector__ .controls svg {
height: 28px;
height: 7vw;
margin: 5px auto;
width: 28px;
max-height: 24px;
max-width: 24px;
width: 7vw;
}

__selector__ .overlay {
Expand All @@ -98,10 +114,12 @@ __selector__ .overlay div {
border-radius: 100px;
border-radius: 100px;
display: flex;
height: 200px;
height: 20vw;
justify-content: center;
position: relative;
width: 200px;
max-height: 200px;
max-width: 200px;
width: 20vw;
}

__selector__ .overlay svg {
Expand Down
Loading

0 comments on commit 9b6e8b4

Please sign in to comment.