diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 0000000..202e929 --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,27 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build: + runs-on: ubuntu-latest + + # Ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs#example-using-npm + # Did not commit package-lock.json file therefore cannot use `npm ci` + steps: + - uses: actions/checkout@v4 + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: "22.x" + - name: Install dependencies + run: npm install + - run: npm run build --if-present + - run: npm test diff --git a/README.md b/README.md index 6bac458..a978ddf 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,11 @@ Standard build Format the code `npm run prettier` +๐Ÿงช + +### Test app + +`npm run test` ### Run app ๐Ÿš€ diff --git a/package.json b/package.json index 756e863..0d44d0f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build:watch": "node --watch-path=./src build.js", "build": "node build.js", "prettier": "prettier . --write", - "start": "node dev-server.js" + "start": "node dev-server.js", + "test": "node --test" }, "author": "", "license": "MIT", diff --git a/src/alpaca-map.js b/src/alpaca-map.js index 0f4c31b..0adc4bd 100644 --- a/src/alpaca-map.js +++ b/src/alpaca-map.js @@ -1,3 +1,4 @@ +import { compareExact, compareSparse } from "./utils"; import { LitElement, html, css } from "lit"; import { MarkerClusterer } from "@googlemaps/markerclusterer"; @@ -147,31 +148,36 @@ export default class AlpacaMap extends LitElement { _filterMarkers(element) { const form = new FormData(element.target.parentElement); - console.log( - "element.target.parentElement.id", - element.target.parentElement.id - ); - console.log("has public", form.has("public")); - console.log("has private", form.has("private")); + const templatePublicPrivate = { + public: form.get("public") === "on", + private: form.get("private") === "on", + }; + + // Build up object with user selected values + const templateSelected = {}; + + for (const key of form.keys()) { + if (key !== "private" && key !== "public") { + templateSelected[key] = true; + } + } const markers = this.farms .filter((farm) => { - if (form.has("public") && form.has("private")) { + if (templatePublicPrivate?.public && templatePublicPrivate?.private) { return true; } - if (!form.has("public") && !form.has("private")) { - return false; - } + const obj = { + public: farm?.category?.public, + private: farm?.category?.private, + }; - if (form.has("public") && farm.public) { - return true; - } - - if (form.has("private") && farm.private) { - return true; - } + return compareExact(templatePublicPrivate, obj); + }) + .filter((farm) => { + return compareSparse(templateSelected, farm?.category); }) .map((farm) => { return farm._marker; @@ -180,8 +186,7 @@ export default class AlpacaMap extends LitElement { this.cluster.clearMarkers(); this.cluster.addMarkers(markers); - console.log(markers.length); - console.log("_filterMarkers"); + console.log("markers.length", markers.length); } render() { @@ -193,6 +198,24 @@ export default class AlpacaMap extends LitElement { + + + + + + + + + + + + + + + + + +
diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..559298f --- /dev/null +++ b/src/utils.js @@ -0,0 +1,18 @@ +export const compareExact = (template, obj) => { + let templateKeys = Object.keys(template); + + if (templateKeys.length === Object.keys(obj).length) { + return templateKeys.every( + (key) => obj.hasOwnProperty(key) && obj[key] === template[key] + ); + } + return false; +}; + +export const compareSparse = (template, obj) => { + let templateKeys = Object.keys(template); + + return templateKeys.every( + (key) => obj.hasOwnProperty(key) && obj[key] === template[key] + ); +}; diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 0000000..2297fbc --- /dev/null +++ b/test/utils.js @@ -0,0 +1,59 @@ +import { compareExact, compareSparse } from "../src/utils.js"; +import assert from "node:assert/strict"; +import { test } from "node:test"; + +test(`compareExact() of equal objects - return true`, () => { + const template = { + private: false, + public: true, + }; + const obj = { private: false, public: true }; + + assert.equal(compareExact(template, obj), true); +}); + +test(`compareExact() of non equal objects - return false`, () => { + const template = { + private: false, + public: true, + }; + const obj = { private: true, public: true }; + + assert.equal(compareExact(template, obj), false); +}); + +test(`compareSparse() contains equal key, values - return true`, () => { + const template = { + bookable: true, + shop: true, + }; + + const obj = { + alpacaSales: true, + alpacaWalking: true, + bookable: true, + shop: true, + overnightStay: true, + studServices: false, + }; + + assert.equal(compareSparse(template, obj), true); +}); + +test(`compareSparse() contains non-equal key, values - return false`, () => { + const template = { + bookable: true, + shop: true, + }; + + const obj = { + alpacaSales: true, + alpacaWalking: true, + bookable: false, + shop: true, + overnightStay: true, + studServices: false, + }; + + assert.equal(compareSparse(template, obj), false); +});