Add tests

This commit is contained in:
uwap 2022-12-31 09:04:15 +01:00
parent 3bd6b0ac2c
commit a64f40b6cc
11 changed files with 2252 additions and 21 deletions

View file

@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh" . "$(dirname -- "$0")/_/husky.sh"
npm test npm test
npm run lint

198
jest.config.ts Normal file
View file

@ -0,0 +1,198 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/
export default {
// All imported modules in your tests should be mocked automatically
// automock: false,
// Stop running tests after `n` failures
// bail: 0,
// The directory where Jest should store its cached dependency information
// cacheDirectory: "C:\\Users\\theuw\\AppData\\Local\\Temp\\jest",
// Automatically clear mock calls, instances, contexts and results before every test
// clearMocks: false,
// Indicates whether the coverage information should be collected while executing the test
// collectCoverage: false,
// An array of glob patterns indicating a set of files for which coverage information should be collected
// collectCoverageFrom: undefined,
// The directory where Jest should output its coverage files
// coverageDirectory: undefined,
// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],
// Indicates which provider should be used to instrument code for coverage
coverageProvider: "v8",
// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],
// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: undefined,
// A path to a custom dependency extractor
// dependencyExtractor: undefined,
// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,
// The default configuration for fake timers
// fakeTimers: {
// "enableGlobally": false
// },
// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],
// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: undefined,
// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: undefined,
// A set of global variables that need to be available in all test environments
// globals: {},
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",
// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
// An array of file extensions your modules use
// moduleFileExtensions: [
// "js",
// "mjs",
// "cjs",
// "jsx",
// "ts",
// "tsx",
// "json",
// "node"
// ],
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// moduleNameMapper: {},
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
// Activates notifications for test results
// notify: false,
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",
// A preset that is used as a base for Jest's configuration
// preset: undefined,
// Run tests from one or more projects
// projects: undefined,
// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
// Automatically reset mock state before every test
// resetMocks: false,
// Reset the module registry before running each individual test
// resetModules: false,
// A path to a custom resolver
// resolver: undefined,
// Automatically restore mock state and implementation before every test
// restoreMocks: false,
// The root directory that Jest should scan for tests and modules within
// rootDir: undefined,
// A list of paths to directories that Jest should use to search for files in
// roots: [
// "<rootDir>"
// ],
// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",
// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],
// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],
// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],
// The test environment that will be used for testing
testEnvironment: "screeps-jest",
// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
// Adds a location field to test results
// testLocationInResults: false,
// The glob patterns Jest uses to detect test files
// testMatch: [
// "**/__tests__/**/*.[jt]s?(x)",
// "**/?(*.)+(spec|test).[tj]s?(x)"
// ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],
// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],
// This option allows the use of a custom results processor
// testResultsProcessor: undefined,
// This option allows use of a custom test runner
// testRunner: "jest-circus/runner",
// A map from regular expressions to paths to transformers
transform: {
"^.+\\.(t|j)sx?$": ["@swc/jest"],
},
extensionsToTreatAsEsm: ['.ts', '.tsx'],
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "\\\\node_modules\\\\",
// "\\.pnp\\.[^\\\\]+$"
// ],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
// Indicates whether each individual test should be reported during the run
// verbose: undefined,
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],
// Whether to use watchman for file crawling
// watchman: true,
};

View file

@ -8,7 +8,7 @@
"build": "npx spack", "build": "npx spack",
"lint": "npx eslint src/", "lint": "npx eslint src/",
"prepare": "husky install", "prepare": "husky install",
"test": "yarn lint", "test": "jest",
"push": "yarn build && node ./upload.js" "push": "yarn build && node ./upload.js"
}, },
"dependencies": { "dependencies": {
@ -16,12 +16,19 @@
}, },
"devDependencies": { "devDependencies": {
"@swc/cli": "^0.1.57", "@swc/cli": "^0.1.57",
"@swc/core": "^1.3.23", "@swc/core": "^1.3.24",
"@swc/jest": "^0.2.24",
"@types/jest": "^29.2.5",
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.47.0", "@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0", "@typescript-eslint/parser": "^5.47.0",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"eslint": "^8.30.0", "eslint": "^8.30.0",
"husky": "^8.0.0", "husky": "^8.0.0",
"jest": "^29.3.1",
"lodash": "^4.17.21",
"screeps-jest": "^2.0.2",
"ts-node": "^10.9.1",
"typescript": "^4.9.4" "typescript": "^4.9.4"
} }
} }

View file

@ -51,7 +51,6 @@ export const createAction = (name: string, action: (creep: Creep) => Action): Ac
if ((creep.memory.state ?? 0) > state) { if ((creep.memory.state ?? 0) > state) {
return Success(creep, state); return Success(creep, state);
} }
//console.log(`[${creep.name}] Running action ${name}`)
return action(creep)(creep, state); return action(creep)(creep, state);
} }
} }

View file

@ -0,0 +1,12 @@
const BodyPartCosts = {
[MOVE]: 50,
[WORK]: 100,
[CARRY]: 50,
[ATTACK]: 80,
[RANGED_ATTACK]: 150,
[HEAL]: 250,
[CLAIM]: 600,
[TOUGH]: 10
}
export default BodyPartCosts;

View file

@ -15,7 +15,7 @@ export const Clerk: WorkerDefinition = {
.repeat(), .repeat(),
name: 'clerk', name: 'clerk',
requiredCreeps: (room: Room) => 2, requiredCreeps: (room: Room) => 2,
bodyDefinition: (energy: number) => [WORK].concat(new Array(Math.floor(energy / 150)).fill([MOVE, CARRY, CARRY]).reduce((x, y) => x.concat(y), [])), bodyDefinition: (energy: number) => energy < 100 ? [] : [WORK].concat(new Array(Math.floor((energy - 100) / 150)).fill([MOVE, CARRY, CARRY]).reduce((x, y) => x.concat(y), [])),
motivationalThougts: [ motivationalThougts: [
"Carrying 🎒", "Carrying 🎒",
"💗 working" "💗 working"

View file

@ -9,7 +9,7 @@ export const Miner: WorkerDefinition = {
.repeat(), .repeat(),
name: 'miner', name: 'miner',
requiredCreeps: (room: Room) => room.find(FIND_STRUCTURES, { filter: { structureType: STRUCTURE_CONTAINER }}).length > 0 ? 4 : 0, requiredCreeps: (room: Room) => room.find(FIND_STRUCTURES, { filter: { structureType: STRUCTURE_CONTAINER }}).length > 0 ? 4 : 0,
bodyDefinition: (energy: number) => [WORK, WORK, MOVE, CARRY].concat(new Array(Math.floor((energy - 300) / 100)).fill(WORK)), bodyDefinition: (energy: number) => energy < 300 ? [] : [WORK, WORK, MOVE, CARRY].concat(new Array(Math.floor((energy - 300) / 100)).fill(WORK)),
motivationalThougts: [ motivationalThougts: [
"RocknStone" "RocknStone"
] ]

4
src/Workers/index.ts Normal file
View file

@ -0,0 +1,4 @@
export { Clerk } from "./Clerk";
export { Constructor } from "./Constructor";
export { Miner } from "./Miner";
export { Upgrader } from "./Upgrader";

View file

@ -0,0 +1,13 @@
import BodyPartCosts from '../Constants/BodyPartCosts';
import * as Workers from './index';
describe('Test Creep Workers', () => {
console.log(Workers.Clerk)
for (const [moduleName, worker] of Object.entries(Workers)) {
test(`${moduleName}: Body parts cost calculation is correct`, () => {
for (let cost = 0; cost < 1500; cost++) {
expect(worker.bodyDefinition(cost).map((x) => BodyPartCosts[x]).reduce((x, y) => x + y, 0)).toBeLessThanOrEqual(cost);
}
});
}
});

View file

@ -2,14 +2,15 @@ export interface WorkerDefinition {
runAction: (creep: Creep, spawn: StructureSpawn) => void, runAction: (creep: Creep, spawn: StructureSpawn) => void,
name: string, name: string,
requiredCreeps: (room: Room) => number, requiredCreeps: (room: Room) => number,
bodyDefinition: (energy: number, spawn: StructureSpawn) => BodyPartConstant[], bodyDefinition: (energy: number) => BodyPartConstant[],
motivationalThougts?: Array<string> motivationalThougts?: string[]
} }
export const spawnWorkers = (spawn: StructureSpawn, workers: WorkerDefinition[]): void => { export const spawnWorkers = (spawn: StructureSpawn, workers: WorkerDefinition[]): void => {
for (const worker of workers) { for (const worker of workers) {
for (let i = 0; i < worker.requiredCreeps(spawn.room); i++) { for (let i = 0; i < worker.requiredCreeps(spawn.room); i++) {
const ret = spawn.spawnCreep(worker.bodyDefinition(spawn.store.getCapacity(RESOURCE_ENERGY) + spawn.room.find(FIND_MY_STRUCTURES, { filter: { structureType: STRUCTURE_EXTENSION }}).length * 50, spawn), worker.name + i.toString()); const ret = spawn.spawnCreep(worker.bodyDefinition(
spawn.store.getCapacity(RESOURCE_ENERGY) + (spawn.room.find(FIND_MY_STRUCTURES, { filter: { structureType: STRUCTURE_EXTENSION }}).length * (Object.keys(Game.creeps).length < 2 ? (25 * Object.keys(Game.creeps).length) : 50))), worker.name + i.toString());
if (ret === OK || ret === ERR_NOT_ENOUGH_ENERGY) { if (ret === OK || ret === ERR_NOT_ENOUGH_ENERGY) {
return; return;
} }

2022
yarn.lock

File diff suppressed because it is too large Load diff