diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7ede9eb..6410815 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,7 +7,23 @@ updates: day: "saturday" time: "00:00" commit-message: - prefix: "" + prefix: "chore" + prefix-development: "dev" + include: "scope" + labels: + - "dependencies" + open-pull-requests-limit: 10 + pull-request-branch-name: + separator: "-" + rebase-strategy: "auto" + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: "weekly" + day: "saturday" + time: "00:00" + commit-message: + prefix: "ci" prefix-development: "dev" include: "scope" labels: diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fcacc88..f243466 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,17 +8,15 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - strategy: - matrix: - node-version: ['lts/*'] steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} + node-version-file: .nvmrc - run: | npm install npm i warframe-items@latest + npm i warframe-worldstate-data@latest npm run lint test: name: Test @@ -26,7 +24,7 @@ jobs: needs: lint strategy: matrix: - node-version: [14, 16, 'lts/*'] + node-version: ['lts/gallium', 'lts/hydrogen', 'lts/iron', 'lts/*'] steps: - name: Checkout uses: actions/checkout@v3 @@ -37,29 +35,27 @@ jobs: - name: Test env: CI: true - TWITCH_CLIENT_ID: ${{ secrets.TWITCH_CLIENT_ID }} run: | npm install npm i warframe-items@latest + npm i warframe-worldstate-data@latest npm test coverage: name: Coverage runs-on: ubuntu-latest needs: lint - strategy: - matrix: - node-version: ['lts/*'] steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm i warframe-items@latest + node-version-file: '.nvmrc' + - run: | + npm install + npm i warframe-items@latest + npm i warframe-worldstate-data@latest - run: npm test env: CI: true - TWITCH_CLIENT_ID: ${{ secrets.TWITCH_CLIENT_ID }} - name: Coveralls uses: coverallsapp/github-action@master with: diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 20390ba..3589111 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -11,16 +11,15 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' - name: Install Supplemental Dependencies run: | npm i npm i jsdoc ink-docstrap tsd-jsdoc - name: Build - uses: andstor/jsdoc-action@v1 - with: - output_dir: ./docs - config_file: ./.github/docs/conf.json - front_page: README.md + run: npm run build:docs - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: diff --git a/.github/workflows/regression.yaml b/.github/workflows/regression.yaml index 39e64ec..627327c 100644 --- a/.github/workflows/regression.yaml +++ b/.github/workflows/regression.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14, 16, 'lts/*'] + node-version: ['lts/gallium', 'lts/hydrogen', 'lts/iron', 'lts/*'] steps: - name: Checkout uses: actions/checkout@v3 @@ -21,9 +21,8 @@ jobs: with: node-version: ${{ matrix.node-version }} - name: Test - env: - TWITCH_CLIENT_ID: ${{ secrets.TWITCH_CLIENT_ID }} run: | npm ci npm i warframe-items@latest + npm i warframe-worldstate-data@latest npm test diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 443a06d..0856a73 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -8,30 +8,27 @@ jobs: release: name: Release runs-on: ubuntu-latest - strategy: - matrix: - node-version: [16.x] steps: - name: Checkout uses: actions/checkout@v3 with: token: ${{ secrets.GH_TOKEN }} - - name: Use Node.js ${{ matrix.node-version }} + - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} + node-version-file: '.nvmrc' - name: Test run: | npm ci npm i warframe-items@latest + npm i warframe-worldstate-data@latest npm run lint npm test - name: Semantic Release - uses: cycjimmy/semantic-release-action@v2 + uses: cycjimmy/semantic-release-action@v4 env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} with: - semantic_version: 17 branches: | ['main'] diff --git a/.gitignore b/.gitignore index d2e8c93..f11f4e6 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,6 @@ node_modules test/data.json docs/ wfcd-arsenal-parser-*.tgz -!.github/docs \ No newline at end of file +!.github/docs +.jshintignore +.jshintrc diff --git a/.nvmrc b/.nvmrc index 6c5e45b..2284ba6 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/gallium +lts/hydrogen diff --git a/README.md b/README.md index afdd304..20b6f53 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Documentation is available [here](https://wfcd.github.io/arsenal-parser/) ## Example usage ```javascript -const ArsenalData = require('ArsenalParser'); -const fetch = require('node-fetch'); +import ArsenalData from 'ArsenalParser.js'; +import fetch from 'node-fetch.js'; const baseURL = 'https://content.warframe.com/dynamic/twitch/getActiveLoadout.php?account='; diff --git a/package.json b/package.json index e06265e..a3374a4 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,13 @@ "main": "src/ArsenalParser.js", "types": "./types/src/ArsenalParser.d.ts", "public": true, + "type": "module", + "exports": { + ".": { + "import": "./src/ArsenalParser.js", + "types": "./types/src/ArsenalParser.d.ts" + } + }, "files": [ "src", "LICENSE", @@ -13,26 +20,25 @@ ], "devDependencies": { "@types/chai": "^4.2.16", - "@types/node-fetch": "^2.6.1", - "@wfcd/eslint-config": "^1.1.6", + "@wfcd/eslint-config": "^1.6.1", + "c8": "^9.1.0", "chai": "^4.3.4", "chai-json-equal": "^0.0.1", "coveralls": "^3.1.0", - "install-peerdeps": "2.0.3", + "install-peerdeps": "^3.0.3", "mocha": "^10.0.0", - "node-fetch": "^2.6.1", - "nyc": "^15.1.0", "typescript": "^5.0.2" }, "scripts": { - "test": "nyc mocha", + "test": "c8 mocha", "coverage": "npm test && nyc report --reporter=text-lcov | coveralls", "lint": "eslint src/ test/", "lint:fix": "eslint src/ test/ --fix", "prepublishOnly": "npm run build:types", "build:docs": "jsdoc -c .github/docs/conf.json -d docs", "build:types": "tsc -p tsconfig.declaration.json", - "postinstall": "install-peerdeps @wfcd/eslint-config@^1.1.6 -S" + "postinstall": "install-peerdeps @wfcd/eslint-config@latest -S", + "validate": "npm ls" }, "keywords": [ "warframe", @@ -52,42 +58,13 @@ }, "repository": "https://github.com/wfcd/arsenal-parser", "engines": { - "node": ">=12.18.3", - "npm": ">=6.14.6" + "node": ">=18.19.0" }, "eslintConfig": { - "extends": "@wfcd", + "extends": "@wfcd/eslint-config/esm", "parser": "@babel/eslint-parser", "parserOptions": { - "sourceType": "script" - }, - "rules": { - "valid-jsdoc": [ - "error", - { - "requireReturn": false, - "requireReturnDescription": false, - "preferType": { - "String": "string", - "Number": "number", - "Boolean": "boolean", - "Function": "function", - "object": "Object", - "date": "Date", - "error": "Error" - }, - "prefer": { - "return": "returns" - } - } - ], - "no-underscore-dangle": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "peerDependencies": true - } - ] + "sourceType": "module" } }, "babel": { @@ -109,7 +86,7 @@ "exit": true, "spec": "test/**/*.spec.js" }, - "nyc": { + "c8": { "reporter": [ "lcov", "text" @@ -117,6 +94,7 @@ "skip-full": true }, "peerDependencies": { - "warframe-items": "^1.1260.46" + "warframe-items": "^1.1262.0", + "warframe-worldstate-data": "^2.3.1" } } diff --git a/src/Archwing.js b/src/Archwing.js index a084048..4e7bc35 100644 --- a/src/Archwing.js +++ b/src/Archwing.js @@ -1,10 +1,11 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { items, loadMods, mapColors } = require('./utils'); +const { findItem, loadMods } = find; +const { mapColors } = colors; -module.exports = class WarframeArchwing { +export default class WarframeArchwing { constructor(archwing) { - this.archwing = items.find((item) => item.uniqueName === archwing.uniqueName) || archwing; + this.archwing = findItem(archwing.uniqueName) || archwing; delete this.archwing.components; delete this.archwing.patchlogs; this.xp = archwing.xp; @@ -16,4 +17,4 @@ module.exports = class WarframeArchwing { attachments: mapColors(archwing.attcol), }; } -}; +} diff --git a/src/ArsenalParser.js b/src/ArsenalParser.js index e0e4a09..c53a351 100644 --- a/src/ArsenalParser.js +++ b/src/ArsenalParser.js @@ -1,15 +1,13 @@ -'use strict'; - -const Player = require('./Player'); -const Warframe = require('./Warframe'); -const Weapon = require('./Weapon'); -const Archwing = require('./Archwing'); -const Parazon = require('./Parazon'); -const Amp = require('./OperatorAmp'); -const Companion = require('./Companion'); -const Mech = require('./Mech'); - -module.exports = class ArsenalData { +import Player from './Player.js'; +import Warframe from './Warframe.js'; +import Weapon from './Weapon.js'; +import Archwing from './Archwing.js'; +import Parazon from './Parazon.js'; +import Amp from './OperatorAmp.js'; +import Companion from './Companion.js'; +import Mech from './Mech.js'; + +export default class ArsenalData { constructor(data) { this.account = new Player(data.account || data.accountInfo); @@ -58,4 +56,4 @@ module.exports = class ArsenalData { if (mechExalted && !mechExalted.hide) this.loadout.mech.exalted = new Weapon(mechExalted); } } -}; +} diff --git a/src/Companion.js b/src/Companion.js index fb7d107..f6d8f2a 100644 --- a/src/Companion.js +++ b/src/Companion.js @@ -1,19 +1,17 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { items, loadMods, mapColors } = require('./utils'); - -module.exports = class WarframeCompanion { +const { findItem, loadMods } = find; +const { mapColors } = colors; +export default class WarframeCompanion { constructor(companion) { - this.companion = items.find((item) => item.uniqueName === companion.uniqueName) || companion; + this.companion = findItem(companion.uniqueName) || companion; delete this.companion.patchlogs; delete this.companion.components; this.xp = companion.xp; this.polarized = companion.polarized; if (companion.skins) { - this.cosmetics = companion.skins.map( - (cosmetic) => items.find((item) => item.uniqueName === cosmetic.uniqueName) || cosmetic - ); + this.cosmetics = companion.skins.map((cosmetic) => findItem(cosmetic.uniqueName) || cosmetic); this.cosmetics.forEach((cosmetic) => { /* eslint-disable no-param-reassign */ @@ -35,4 +33,4 @@ module.exports = class WarframeCompanion { this.type = companion.type; if (companion.itemName) this.name = companion.itemName; } -}; +} diff --git a/src/Mech.js b/src/Mech.js index c887fbb..c9e3010 100644 --- a/src/Mech.js +++ b/src/Mech.js @@ -1,8 +1,9 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { loadMods, mapColors, findItem } = require('./utils'); +const { findItem, loadMods } = find; +const { mapColors } = colors; -module.exports = class WarframeMech { +export default class WarframeMech { constructor(mech) { this.mech = findItem(mech.uniqueName) || mech; @@ -39,4 +40,4 @@ module.exports = class WarframeMech { // ?? no idea what this is this.features = mech.features; } -}; +} diff --git a/src/OperatorAmp.js b/src/OperatorAmp.js index 548460b..9b8079e 100644 --- a/src/OperatorAmp.js +++ b/src/OperatorAmp.js @@ -1,21 +1,22 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { items, mapColors } = require('./utils'); +const { findItem } = find; +const { mapColors } = colors; -module.exports = class OperatorAmp { +export default class OperatorAmp { constructor(amp) { this.xp = amp.xp; this.polarized = amp.polarized; - this.amp = items.find((item) => item.uniqueName === amp.uniqueName) || amp; + this.amp = findItem(amp.uniqueName) || amp; if (!amp.modularParts) return; this.parts = { - prism: items.find((item) => item.uniqueName === amp.modularParts.LWPT_AMP_OCULUS) || { + prism: findItem(amp.modularParts.LWPT_AMP_OCULUS) || { uniqueName: amp.modularParts.LWPT_AMP_OCULUS, }, - scaffold: items.find((item) => item.uniqueName === amp.modularParts.LWPT_AMP_CORE) || { + scaffold: findItem(amp.modularParts.LWPT_AMP_CORE) || { uniqueName: amp.modularParts.LWPT_AMP_CORE, }, - brace: items.find((item) => item.uniqueName === amp.modularParts.LWPT_AMP_BRACE) || { + brace: findItem(amp.modularParts.LWPT_AMP_BRACE) || { uniqueName: amp.modularParts.LWPT_AMP_BRACE, }, }; @@ -33,4 +34,4 @@ module.exports = class OperatorAmp { }); this.colors = mapColors(amp.pricol); } -}; +} diff --git a/src/Parazon.js b/src/Parazon.js index 388f66d..3a4d215 100644 --- a/src/Parazon.js +++ b/src/Parazon.js @@ -1,17 +1,16 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { items, loadMods, mapColors } = require('./utils'); +const { findItem, loadMods } = find; +const { mapColors } = colors; -module.exports = class WarframeParazon { +export default class WarframeParazon { constructor(parazon) { this.uniqueName = parazon.uniqueName; this.xp = parazon.xp; this.polarized = parazon.polarized; this.upgrades = loadMods(parazon.upgrades); if (parazon.skins) { - this.cosmetics = parazon.skins.map( - (cosmetic) => items.find((item) => item.uniqueName === cosmetic.uniqueName) || cosmetic - ); + this.cosmetics = parazon.skins.map((cosmetic) => findItem(cosmetic.uniqueName) || cosmetic); this.cosmetics.forEach((cosmetic) => { /* eslint-disable no-param-reassign */ @@ -28,4 +27,4 @@ module.exports = class WarframeParazon { this.colors = mapColors(parazon.pricol); } -}; +} diff --git a/src/Pixel.js b/src/Pixel.js index dfda17b..662c213 100644 --- a/src/Pixel.js +++ b/src/Pixel.js @@ -1,6 +1,4 @@ -'use strict'; - -const Items = require('warframe-items'); +import Items from 'warframe-items'; const items = new Items().filter((i) => i.hexColours); @@ -34,7 +32,7 @@ const position = (ind) => ({ * @property {PaletteCoordinate} */ -module.exports = class Pixel { +export default class Pixel { /** Raw hex value * @type string */ @@ -117,4 +115,4 @@ module.exports = class Pixel { hex: this.#hex, }; } -}; +} diff --git a/src/Player.js b/src/Player.js index b0149cc..3dcf2d7 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,8 +1,8 @@ -'use strict'; +import { find } from 'warframe-items/utilities'; +import { translateFocus } from 'warframe-worldstate-data/utilities'; -const { translateFocus, items } = require('./utils'); - -module.exports = /** Warframe Player information */ class WarframePlayer { +const { findItem } = find; +export default /** Warframe Player information */ class WarframePlayer { /** * Player name * @type {string} @@ -33,7 +33,7 @@ module.exports = /** Warframe Player information */ class WarframePlayer { this.#name = data.playerName; this.#masteryRank = data.masteryRank; this.#lastUpdated = new Date(data.lastUpdated * 1000); - this.#glyph = items.find((item) => item.uniqueName === data.glyph) || data.glyph; + this.#glyph = findItem(data.glyph) || data.glyph; this.#focusSchool = translateFocus(data.focus || ''); } @@ -82,4 +82,4 @@ module.exports = /** Warframe Player information */ class WarframePlayer { focusSchool: this.#focusSchool, }; } -}; +} diff --git a/src/Warframe.js b/src/Warframe.js index 20f0f40..7058377 100644 --- a/src/Warframe.js +++ b/src/Warframe.js @@ -1,10 +1,11 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { items, loadMods, mapColors } = require('./utils'); +const { findItem, loadMods } = find; +const { mapColors } = colors; -module.exports = class Warframe { +export default class Warframe { constructor(frame) { - this.warframe = items.find((item) => item.uniqueName === frame.uniqueName) || frame; + this.warframe = findItem(frame.uniqueName) || frame; delete this.warframe.patchlogs; delete this.warframe.components; delete this.warframe.buildPrice; @@ -18,9 +19,7 @@ module.exports = class Warframe { this.xp = frame.xp; this.polarized = frame.polarized; this.features = frame.polarized; - this.cosmetics = (frame.skins || []).map( - (skin) => items.find((item) => item.uniqueName === skin.uniqueName) || skin - ); + this.cosmetics = (frame.skins || []).map((skin) => findItem(skin.uniqueName) || skin); this.cosmetics.forEach((cosmetic) => { /* eslint-disable no-param-reassign */ @@ -42,4 +41,4 @@ module.exports = class Warframe { attachments: mapColors(frame.attcol), }; } -}; +} diff --git a/src/Weapon.js b/src/Weapon.js index e3f8270..20bd5dc 100644 --- a/src/Weapon.js +++ b/src/Weapon.js @@ -1,21 +1,20 @@ -'use strict'; +import { find, colors } from 'warframe-items/utilities'; -const { items, loadMods, mapColors } = require('./utils'); +const { findItem, loadMods } = find; +const { mapColors } = colors; -module.exports = class WarframeWeapon { +export default class WarframeWeapon { constructor(weapon) { this.xp = weapon.xp; this.polarized = weapon.polarized; this.upgrades = loadMods(weapon.upgrades); if (weapon.itemName) this.itemName = weapon.itemName; - this.cosmetics = (weapon.skins || []).map( - (skin) => items.find((item) => item.uniqueName === skin.uniqueName) || skin - ); + this.cosmetics = (weapon.skins || []).map((skin) => findItem(skin.uniqueName) || skin); if (weapon.modularParts) { const parts = {}; Object.keys(weapon.modularParts).forEach((part) => { - parts[part] = items.find((item) => item.uniqueName === weapon.modularParts[part]) || { + parts[part] = findItem(weapon.modularParts[part]) || { uniqueName: weapon.modularParts[part], }; }); @@ -34,7 +33,7 @@ module.exports = class WarframeWeapon { this.parts = parts; } else { - this.weapon = items.find((item) => item.uniqueName === weapon.uniqueName) || weapon; + this.weapon = findItem(weapon.uniqueName) || weapon; delete this.weapon.components; delete this.weapon.patchlogs; this.colors = mapColors(weapon.pricol); @@ -44,4 +43,4 @@ module.exports = class WarframeWeapon { delete this.weapon.damagePerShot; } } -}; +} diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index c5aed14..0000000 --- a/src/utils.js +++ /dev/null @@ -1,152 +0,0 @@ -'use strict'; - -const Items = require('warframe-items'); - -const Pixel = require('./Pixel'); - -const items = new Items(); - -function translateFocus(focus = '') { - if (focus.includes('Focus/Attack')) { - return 'Madurai'; - } - if (focus.includes('Focus/Defense')) { - return 'Varazin'; - } - if (focus.includes('Focus/Tactic')) { - return 'Naramon'; - } - if (focus.includes('Focus/Power')) { - return 'Zenurik'; - } - if (focus.includes('Focus/Ward')) { - return 'Unairu'; - } - return 'None'; -} - -function translatePolarity(pol = '') { - if (pol.includes('AP_ATTACK')) { - return 'Madurai'; - } - if (pol.includes('AP_DEFENSE')) { - return 'Varazin'; - } - if (pol.includes('AP_TACTIC')) { - return 'Naramon'; - } - if (pol.includes('AP_POWER')) { - return 'Zenurik'; - } - if (pol.includes('AP_WARD')) { - return 'Unairu'; - } - return 'None'; -} - -function loadMods(upgrades = []) { - const arcanes = []; - const mods = []; - upgrades.forEach((upgrade) => { - let upgradeData = items.find((item) => item.uniqueName === upgrade.uniqueName) || upgrade; - - upgradeData.rank = upgrade.rank; - upgradeData.uniqueName = upgrade.uniqueName; - if (upgradeData.levelStats) { - upgradeData.levelStats = upgradeData.levelStats[upgrade.rank] || upgradeData.levelStats; - } - delete upgradeData.drops; - delete upgradeData.patchlogs; - - if (upgradeData.category === 'Arcanes') { - delete upgradeData.tradable; - arcanes.push(upgradeData); - } else if (upgradeData.category === 'Mods') { - if (upgradeData.name.includes('Riven Mod')) { - upgradeData = { - uniqueName: upgradeData.uniqueName, - polarity: translatePolarity(upgrade.pol), - rarity: upgradeData.rarity, - baseDrain: Number(upgradeData.baseDrain), - fusionLimit: upgradeData.fusionLimit, - imageName: upgradeData.imageName, - category: upgradeData.category, - tradable: upgradeData.tradable, - wikiaThumbnail: upgradeData.wikiaThumbnail || undefined, - wikiaUrl: upgradeData.wikiaUrl || undefined, - buffs: upgrade.buffs, - curses: upgrade.curses, - masteryReq: upgrade.lvlReq, - }; - } - delete upgradeData.transmutable; - delete upgradeData.tradable; - mods.push(upgradeData); - } - }); - return { - arcanes, - mods, - }; -} - -/** - * Safely map a color to a pixel - * @param {string|undefined} color hex value to check for existence - * @returns {Pixel|undefined} - */ -const safeColor = (color) => (color ? new Pixel(color) : undefined); - -/** - * Common Color Map - * @typedef {Object} ColorMap - * @property {Pixel} [primary] - * @property {Pixel} [secondary] - * @property {Pixel} [tertiary] - * @property {Pixel} [accents] - * @property {Array} [emissive] - * @property {Array} [energy] - */ - -/** - * @typedef {Object} RawColors - * @property {string} [t0] primary color hex - * @property {string} [t1] secondary color hex - * @property {string} [t2] tertiary color hex - * @property {string} [t3] accent color hex - * @property {string} [m0] first emissive color hex - * @property {string} [m1] second emissive color hex - * @property {string} [en] first energy color hex - * @property {string} [en1] second energy color hex - */ - -/** - * Map DE Colors to common named colors - * @param {RawColors} colors raw colors from api - * @returns {ColorMap|undefined} - */ -function mapColors(colors = undefined) { - if (!colors) return undefined; - return { - primary: safeColor(colors.t0), - secondary: safeColor(colors.t1), - tertiary: safeColor(colors.t2), - accents: safeColor(colors.t3), - emissive: [safeColor(colors.m0), safeColor(colors.m1)].filter((c) => c), - energy: [safeColor(colors.en), safeColor(colors.en1)].filter((c) => c), - }; -} - -const findItem = (uname) => - items - .filter((item) => item && typeof item !== 'undefined' && item.uniqueName) - .find((item) => item.uniqueName === uname); - -module.exports = { - translateFocus, - loadMods, - translatePolarity, - items, - findItem, - mapColors, -}; diff --git a/test/.eslintrc.json b/test/.eslintrc.json deleted file mode 100644 index 86bda9b..0000000 --- a/test/.eslintrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "env": { - "mocha": true - }, - "rules": { - "prefer-arrow-callback": "off", - "func-names": "off", - "no-new": "off", - "no-unused-expressions": "off", - "valid-jsdoc": "off", - "import/no-extraneous-dependencies": ["error", {"devDependencies": true, "peerDependencies": true}], - "import/no-dynamic-require": "off", - "global-require": "off" - } -} diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml new file mode 100644 index 0000000..db0f557 --- /dev/null +++ b/test/.eslintrc.yaml @@ -0,0 +1,17 @@ +env: + mocha: true +parserOptions: + requireConfigFile: false +rules: + prefer-arrow-callback: off + func-names: off + no-new: off + no-unused-expressions: off + valid-jsdoc: off + import/no-extraneous-dependencies: + - error + - devDependencies: true + peerDependencies: true + import/no-dynamic-require: off + global-require: off + import/prefer-default-export: off diff --git a/test/regression/fetch.js b/test/regression/fetch.js index 9a9cc6d..b89f536 100644 --- a/test/regression/fetch.js +++ b/test/regression/fetch.js @@ -1,32 +1,30 @@ -'use strict'; - // based off of derrod's usage on github: https://github.com/derrod/warfra_re/blob/master/twitch/arsenal.py - -const fetch = require('node-fetch'); - const BASE_URL = 'https://content.warframe.com/dynamic/twitch/getActiveLoadout.php?account='; -const CLIENT_ID = process.env.TWITCH_CLIENT_ID; -const WF_ARSENAL_ID = 'ud1zj704c0eb1s553jbkayvqxjft97'; +const CLIENT_ID = 'kimne78kx3ncx6brgo4mv6wki5h1ko'; // Twitch's client id +const WF_ARSENAL_ID = 'ud1zj704c0eb1s553jbkayvqxjft97'; // wf arsenal extension const TWITCH_CHANNEL_ID = '89104719'; // tobitenno const cache = {}; -const v5Token = async () => { - return ( - await fetch(`https://api.twitch.tv/v5/channels/${TWITCH_CHANNEL_ID}/extensions`, { - headers: { - 'client-id': CLIENT_ID, - }, - }).then((d) => d.json()) - )?.tokens?.find((s) => s.extension_id === WF_ARSENAL_ID)?.token; +const gqlToken = async () => { + const raw = await fetch(`https://gql.twitch.tv/gql`, { + method: 'POST', + headers: { + 'client-id': CLIENT_ID, + }, + body: `[{"operationName":"ExtensionsForChannel","variables":{"channelID":"${TWITCH_CHANNEL_ID}"},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"d52085e5b03d1fc3534aa49de8f5128b2ee0f4e700f79bf3875dcb1c90947ac3"}}}]`, + }).then((d) => d.json()); + return raw?.[0]?.data?.user?.channel?.selfInstalledExtensions?.find((s) => { + return s?.token?.extensionID === WF_ARSENAL_ID; + })?.token?.jwt; }; -module.exports = async (username) => { +export default async (username) => { if (!CLIENT_ID) throw new Error('No defined client id'); if (cache[username]) return cache[username]; - const token = await v5Token(); + const token = await gqlToken(); // Fetch the data for the specified username const data = await fetch(BASE_URL + encodeURIComponent(username.toLowerCase()), { headers: { diff --git a/test/regression/module.spec.js b/test/regression/module.spec.js index 483dbcc..ab43f40 100644 --- a/test/regression/module.spec.js +++ b/test/regression/module.spec.js @@ -1,10 +1,8 @@ -'use strict'; +import { assert } from 'chai'; -const { assert } = require('chai'); +import ArsenalData from '../../src/ArsenalParser.js'; -const ArsenalData = require('../../src/ArsenalParser'); - -const fetch = require('./fetch'); +import fetch from './fetch.js'; const working = async () => { try { diff --git a/test/unit/archwing.spec.js b/test/unit/archwing.spec.js index 44c82cc..8188701 100644 --- a/test/unit/archwing.spec.js +++ b/test/unit/archwing.spec.js @@ -1,9 +1,7 @@ -'use strict'; - -const { assert } = require('chai'); +import { assert } from 'chai'; // Archwing.js testing -const WarframeArchwing = require('../../src/Archwing'); +import WarframeArchwing from '../../src/Archwing.js'; describe('WarframeArchwing', () => { describe('#constructor', () => { diff --git a/test/unit/companion.spec.js b/test/unit/companion.spec.js index ee0f49e..c3e2f45 100644 --- a/test/unit/companion.spec.js +++ b/test/unit/companion.spec.js @@ -1,17 +1,15 @@ -'use strict'; +import { assert } from 'chai'; +import Items from 'warframe-items'; -const { assert } = require('chai'); -const Items = require('warframe-items'); +// Companion.js testing +import WarframeCompanion from '../../src/Companion.js'; +import { marshall } from '../utils.js'; const items = new Items({ category: ['Pets'] }); const cheshire = items.find((i) => i.uniqueName === '/Lotus/Types/Game/CatbrowPet/CheshireCatbrowPetPowerSuit'); delete cheshire.patchlogs; -// Companion.js testing -const WarframeCompanion = require('../../src/Companion'); -const { marshall } = require('../utils'); - describe('WarframeCompanion', () => { describe('#constructor', () => { it('should handle creating the companion object', () => { diff --git a/test/unit/mech.spec.js b/test/unit/mech.spec.js index aefcd1d..ba6404f 100644 --- a/test/unit/mech.spec.js +++ b/test/unit/mech.spec.js @@ -1,10 +1,8 @@ -'use strict'; - -const { assert } = require('chai'); +import { assert } from 'chai'; // Companion.js testing -const Items = require('warframe-items'); +import Items from 'warframe-items'; -const WarframeMech = require('../../src/Mech'); +import WarframeMech from '../../src/Mech.js'; const items = new Items(); diff --git a/test/unit/mock.spec.js b/test/unit/mock.spec.js index 589126c..f298514 100644 --- a/test/unit/mock.spec.js +++ b/test/unit/mock.spec.js @@ -1,17 +1,23 @@ -'use strict'; +import { assert } from 'chai'; +import ArsenalData from '@wfcd/arsenal-parser'; -const { assert } = require('chai'); +import Player from '../../src/Player.js'; -const example = (number) => require(`../data/exampleData${number}.json`); - -const ArsenalData = require('../../src/ArsenalParser'); +const examples = ( + await Promise.all( + new Array(6).fill(0).map((_, i) => import(`../data/exampleData${i + 1}.json`, { assert: { type: 'json' } })) + ) +).map((p) => p.default); // Testing the main class describe('Mock ArsenalData', () => { describe('#constructor', () => { - it('should handle real data', () => { - ['1', '2', '3', '4', '5', '6'].forEach((ind) => { - assert.isOk(new ArsenalData(example(ind)), `${ind} failed`); + it('should handle real data', async function () { + this.timeout(10000); + examples.forEach((data) => { + const parsed = new ArsenalData(data); + assert.instanceOf(parsed.account, Player); + assert.isObject(parsed.loadout); }); }); }); diff --git a/test/unit/operatoramp.spec.js b/test/unit/operatoramp.spec.js index 8743500..be319e9 100644 --- a/test/unit/operatoramp.spec.js +++ b/test/unit/operatoramp.spec.js @@ -1,14 +1,12 @@ -'use strict'; +import { assert } from 'chai'; +import Items from 'warframe-items'; -const { assert } = require('chai'); -const Items = require('warframe-items'); +// OperatorAmp.js testing +import OperatorAmp from '../../src/OperatorAmp.js'; +import { marshall } from '../utils.js'; const items = new Items(); -// OperatorAmp.js testing -const OperatorAmp = require('../../src/OperatorAmp'); -const { marshall } = require('../utils'); - describe('OperatorAmp', () => { describe('#constructor', () => { it('should handle real data', () => { diff --git a/test/unit/parazon.spec.js b/test/unit/parazon.spec.js index fafe345..490fd45 100644 --- a/test/unit/parazon.spec.js +++ b/test/unit/parazon.spec.js @@ -1,10 +1,8 @@ -'use strict'; - -const { assert } = require('chai'); +import { assert } from 'chai'; // Parazon.js testing -const WarframeParazon = require('../../src/Parazon'); -const { marshall } = require('../utils'); +import WarframeParazon from '../../src/Parazon.js'; +import { marshall } from '../utils.js'; describe('WarframeParazon', () => { describe('#constructor', () => { diff --git a/test/unit/pixel.spec.js b/test/unit/pixel.spec.js index 49906c3..05e0b63 100644 --- a/test/unit/pixel.spec.js +++ b/test/unit/pixel.spec.js @@ -1,16 +1,15 @@ -'use strict'; +import { colors } from 'warframe-items/utilities'; +import { assert } from 'chai'; -const { assert } = require('chai'); +const { safeColor } = colors; // Archwing.js testing -const Pixel = require('../../src/Pixel'); - describe('Pixel', () => { describe('#constructor', () => { it('should parse and match hex codes', () => { const sampleCodes = ['2E203D', '9078EA', 'D6A3EC', '49667C', 'E6B0FE', 'E6B0FE', '2E203D']; sampleCodes.forEach((hex) => { - const pixel = new Pixel(hex); + const pixel = safeColor(hex); assert.equal(pixel.hex, hex, 'Hex mismatch'); assert.isNotEmpty(pixel.matches, 'No matches resolved'); assert.isNotEmpty(pixel.palettes, 'Real pixels should give palettes'); @@ -20,7 +19,7 @@ describe('Pixel', () => { it('should handle being passed an unknown hex', () => { const fakeHex = '023nva'; - const fakePixel = new Pixel(fakeHex); + const fakePixel = safeColor(fakeHex); assert.isOk(fakePixel); assert.equal(fakePixel.hex, fakeHex, 'Hex mismatch'); diff --git a/test/unit/player.spec.js b/test/unit/player.spec.js index a9bf9cf..dc01d89 100644 --- a/test/unit/player.spec.js +++ b/test/unit/player.spec.js @@ -1,10 +1,8 @@ -'use strict'; - -const { assert } = require('chai'); +import { assert } from 'chai'; // Player.js testing -const WarframePlayer = require('../../src/Player'); -const { marshall } = require('../utils'); +import WarframePlayer from '../../src/Player.js'; +import { marshall } from '../utils.js'; describe('WarframePlayer', () => { describe('#constructor', () => { diff --git a/test/unit/utils.spec.js b/test/unit/utils.spec.js index ba4f693..2741859 100644 --- a/test/unit/utils.spec.js +++ b/test/unit/utils.spec.js @@ -1,15 +1,16 @@ -'use strict'; +import { assert } from 'chai'; +import Items from 'warframe-items'; +import { find } from 'warframe-items/utilities'; +import { translateFocus, translatePolarity } from 'warframe-worldstate-data/utilities'; -const { assert } = require('chai'); -const Items = require('warframe-items'); +// js Testing +import { marshall } from '../utils.js'; -const items = new Items(); +const { loadMods } = find; -// Utils.js Testing -const utils = require('../../src/utils'); -const { marshall } = require('../utils'); +const items = new Items(); -describe('utils', () => { +describe('utilities', () => { describe('#loadMods', () => { it('Should parse an arcane correctly', () => { const sampleArcane = { @@ -17,7 +18,7 @@ describe('utils', () => { rank: 5, }; - const arcaneEnergize = utils.loadMods([sampleArcane]); + const arcaneEnergize = loadMods([sampleArcane]); assert.deepEqual( marshall(arcaneEnergize.arcanes[0]), @@ -31,7 +32,7 @@ describe('utils', () => { rank: 5, }; - const hunterCommand = utils.loadMods([sampleMod]); + const hunterCommand = loadMods([sampleMod]); assert.deepEqual( hunterCommand.mods[0], @@ -53,7 +54,7 @@ describe('utils', () => { pol: 'AP_DEFENSE', }; - const rivenMod = utils.loadMods([sampleRiven]); + const rivenMod = loadMods([sampleRiven]); const expectedRiven = { uniqueName: '/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare', @@ -79,19 +80,19 @@ describe('utils', () => { }); it('should ignore mods that are unknown', () => { assert.deepEqual( - utils.loadMods([{ uniqueName: 'MyFakeModName' }]), + loadMods([{ uniqueName: 'MyFakeModName' }]), { arcanes: [], mods: [] }, 'Nonexistant mods not ignored' ); }); it('should handle being passed an undefined value', () => { - assert.deepEqual(utils.loadMods(undefined), { arcanes: [], mods: [] }, 'Failed with no input'); + assert.deepEqual(loadMods(undefined), { arcanes: [], mods: [] }, 'Failed with no input'); }); it('should handle being passed a mod that should not have a rank assigned', () => { const sampleParazonMod = { uniqueName: '/Lotus/Upgrades/Mods/DataSpike/Cipher/AutoHackMod', }; - const parazonMod = utils.loadMods([sampleParazonMod]); + const parazonMod = loadMods([sampleParazonMod]); assert.deepEqual( parazonMod.mods[0].levelStats[0], { stats: ['+30% chance to auto complete Hacking'] }, @@ -102,26 +103,26 @@ describe('utils', () => { describe('#translateFocus', () => { it('should respond with None if undefined', () => { - assert.equal(utils.translateFocus(undefined), 'None', 'Undefined focus was not None'); + assert.equal(translateFocus(undefined), 'None', 'Undefined focus was not None'); }); it('should correctly determine focus schools', () => { - assert.equal(utils.translateFocus('Focus/Attack'), 'Madurai', 'Focus school incorrect'); - assert.equal(utils.translateFocus('Focus/Defense'), 'Varazin', 'Focus school incorrect'); - assert.equal(utils.translateFocus('Focus/Tactic'), 'Naramon', 'Focus school incorrect'); - assert.equal(utils.translateFocus('Focus/Power'), 'Zenurik', 'Focus school incorrect'); - assert.equal(utils.translateFocus('Focus/Ward'), 'Unairu', 'Focus school incorrect'); + assert.equal(translateFocus('Focus/Attack'), 'Madurai', 'Focus school incorrect'); + assert.equal(translateFocus('Focus/Defense'), 'Varazin', 'Focus school incorrect'); + assert.equal(translateFocus('Focus/Tactic'), 'Naramon', 'Focus school incorrect'); + assert.equal(translateFocus('Focus/Power'), 'Zenurik', 'Focus school incorrect'); + assert.equal(translateFocus('Focus/Ward'), 'Unairu', 'Focus school incorrect'); }); }); describe('#translatePolarity', () => { it('should respond with None if undefined', () => { - assert.equal(utils.translatePolarity(undefined), 'None', 'Undefined polarity was not None'); + assert.equal(translatePolarity(undefined), 'None', 'Undefined polarity was not None'); }); it('should correctly determine polarities', () => { - assert.equal(utils.translatePolarity('AP_ATTACK'), 'Madurai', 'Polarity incorrect'); - assert.equal(utils.translatePolarity('AP_DEFENSE'), 'Varazin', 'Polarity incorrect'); - assert.equal(utils.translatePolarity('AP_TACTIC'), 'Naramon', 'Polarity incorrect'); - assert.equal(utils.translatePolarity('AP_POWER'), 'Zenurik', 'Polarity incorrect'); - assert.equal(utils.translatePolarity('AP_WARD'), 'Unairu', 'Polarity incorrect'); + assert.equal(translatePolarity('AP_ATTACK'), 'Madurai', 'Polarity incorrect'); + assert.equal(translatePolarity('AP_DEFENSE'), 'Varazin', 'Polarity incorrect'); + assert.equal(translatePolarity('AP_TACTIC'), 'Naramon', 'Polarity incorrect'); + assert.equal(translatePolarity('AP_POWER'), 'Zenurik', 'Polarity incorrect'); + assert.equal(translatePolarity('AP_WARD'), 'Unairu', 'Polarity incorrect'); }); }); }); diff --git a/test/unit/warframe.spec.js b/test/unit/warframe.spec.js index 7891bf0..c280538 100644 --- a/test/unit/warframe.spec.js +++ b/test/unit/warframe.spec.js @@ -1,10 +1,8 @@ -'use strict'; - -const { assert } = require('chai'); +import { assert } from 'chai'; // Warframe.js testing -const Warframe = require('../../src/Warframe'); -const { marshall } = require('../utils'); +import Warframe from '../../src/Warframe.js'; +import { marshall } from '../utils.js'; describe('Warframe', () => { describe('#constructor', () => { diff --git a/test/unit/weapon.spec.js b/test/unit/weapon.spec.js index 536b443..5307796 100644 --- a/test/unit/weapon.spec.js +++ b/test/unit/weapon.spec.js @@ -1,9 +1,7 @@ -'use strict'; - -const { assert } = require('chai'); +import { assert } from 'chai'; // Weapon.js testing -const WarframeWeapon = require('../../src/Weapon'); +import WarframeWeapon from '../../src/Weapon.js'; describe('WarframeWeapon', () => { describe('#constructor', () => { diff --git a/test/utils.js b/test/utils.js index ac34943..49f4ee8 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,10 +1,6 @@ -'use strict'; - -module.exports = { - marshall: (obj) => { - const parsed = JSON.parse(JSON.stringify(obj)); - if (parsed.wikiaUrl) delete parsed.wikiaUrl; - if (parsed.wikiaThumbnail) delete parsed.wikiaThumbnail; - return parsed; - }, +export const marshall = (obj) => { + const parsed = JSON.parse(JSON.stringify(obj)); + if (parsed.wikiaUrl) delete parsed.wikiaUrl; + if (parsed.wikiaThumbnail) delete parsed.wikiaThumbnail; + return parsed; };