Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ name: Node.js CI
on:
push:
pull_request:
types: [opened]

# Define permissions needed for the GITHUB_TOKEN
permissions:
contents: read
actions: read

jobs:
build:
Expand All @@ -27,3 +33,40 @@ jobs:
name: subspace_storage
path: ./dist
if-no-files-found: error

test:
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
factorio-version: ['0.17.79', '1.0.0', '1.1.110', '2.0.39']
fail-fast: false

steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 22.x

# Install xz-utils for tar.xz extraction
- name: Install xz-utils
run: sudo apt-get update && sudo apt-get install -y xz-utils

# Download the built artifacts
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: subspace_storage
path: ./dist

- name: Install dependencies
run: pnpm i --no-frozen-lockfile

- name: Run integration test
env:
FACTORIO_VERSION: ${{ matrix.factorio-version }}
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: npm test
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ node_modules/
package-lock.json

# Blender save versions
*.blend[1-9]
*.blend[1-9]

# Factorio test files
test/factorio*
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,32 @@ Build Instructions
Install Node.js version 10 or later and run `npm install` then run `node build`.
It will output the built mod into the `dist` folder by default.
See `node build --help` for options.

Testing
------------------

To run the integration test:

```bash
# Basic test using a dummy clusterio_lib mod
npm test

# Test with the latest clusterio_lib from GitHub Actions
GITHUB_TOKEN=your_github_token npm test
```

The integration test will:
1. Download and set up a Factorio headless server
2. Build and install the Subspace Storage mod
3. When provided with a GitHub token, download the latest clusterio_lib from GitHub Actions
4. Run Factorio to verify that the mod loads correctly

Note: To download the clusterio_lib mod from GitHub Actions, you need a GitHub personal access token with the `public_repo` scope. If not provided, the test will fall back to using a dummy clusterio_lib mod.

### CI Configuration

For CI environments, you should store the GitHub token as a secret:

1. Go to your repository Settings → Secrets and variables → Actions
2. Add a new repository secret named `GH_PAT` with your GitHub personal access token
3. The CI workflow is already configured to use this secret when running tests
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"repository": "https://github.com/clusterio/subspace_storage",
"license": "MIT",
"scripts": {
"build": "node build.js"
"build": "node build.js",
"test": "node test/integration.test.js && node test/lua_commands.test.js"
},
"engines": {
"node": ">=10"
Expand All @@ -13,6 +14,11 @@
"jszip": "^3.10.1",
"klaw": "^4.1.0",
"sharp": "^0.33.5",
"unzipper": "^0.10.14",
"yargs": "^17.7.2"
},
"devDependencies": {
"rcon-client": "^4.2.5",
"tar": "^6.2.0"
}
}
5 changes: 4 additions & 1 deletion src/control.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local mod_gui = require("mod-gui")
local clusterio_api = require("__clusterio_lib__/api")
local lib_compat = require("__clusterio_lib__/compat")

local compat = require("compat")
local compat = require("lib_compat")


-- Entities which are not allowed to be placed outside the restriction zone
Expand Down Expand Up @@ -204,6 +204,9 @@ script.on_event(defines.events.on_robot_built_entity, function(event)
OnBuiltEntity(event)
end)

script.on_event(defines.events.script_raised_built, function(event)
OnBuiltEntity(event)
end)

----------------------------
--[[Thing killing events]]--
Expand Down
8 changes: 4 additions & 4 deletions src/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
{
"version": "2.1.17",
"factorio_version": "0.17",
"additional_files": { "compat.lua": ["compat", "factorio_0.17.lua"] }
"additional_files": { "lib_compat.lua": ["compat", "factorio_0.17.lua"] }
},
{
"version": "2.1.10",
"factorio_version": "1.0",
"additional_files": { "compat.lua": ["compat", "factorio_1.0.lua"] }
"additional_files": { "lib_compat.lua": ["compat", "factorio_1.0.lua"] }
},
{
"version": "2.1.11",
"factorio_version": "1.1",
"additional_files": { "compat.lua": ["compat", "factorio_1.1.lua"] }
"additional_files": { "lib_compat.lua": ["compat", "factorio_1.1.lua"] }
},
{
"version": "2.1.20",
"factorio_version": "2.0",
"additional_files": { "compat.lua": ["compat", "factorio_2.0.lua"] }
"additional_files": { "lib_compat.lua": ["compat", "factorio_2.0.lua"] }
}
],
"title": "Subspace Storage (Alpha)",
Expand Down
2 changes: 1 addition & 1 deletion src/prototypes/entities.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local compat = require("compat")
local compat = require("lib_compat")
local icons = require("entity_icons")
local pictures = require("entity_pictures")

Expand Down
62 changes: 62 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Subspace Storage Integration Tests

This directory contains integration tests for the Subspace Storage mod. These tests verify that the mod loads correctly and that its Lua commands interact with the game as expected.

## Test Files

- `integration.test.js`: Basic test that verifies the mod loads correctly
- `lua_commands_test.js`: Tests that verify the Lua commands interact with the game correctly

## Running the Tests

### Environment Variables

The tests use the following environment variables:

- `FACTORIO_VERSION`: The version of Factorio to test with (optional, defaults to 1.1.110)
- `MOD_VERSION`: The version of the mod to test with (optional)
- `GITHUB_TOKEN`: The GitHub token to use for downloading clusterio_lib from GitHub Actions (required for CI)

### Running the Basic Integration Test

```bash
node integration.test.js
```

This test verifies that the mod loads correctly without any errors.

### Running the Lua Commands Test

```bash
node lua_commands_test.js
```

This test verifies that the Lua commands interact with the game correctly.

## How the Tests Work

The tests work by:

1. Downloading a headless version of Factorio
2. Setting up a mod directory with the Subspace Storage mod and its dependencies
3. Creating a test save file
4. Running Factorio with Lua scripts that test specific functionality
5. Analyzing the output to determine if the tests passed or failed

## Adding New Tests

To add a new test:

1. Create a new Lua script in the `createTestScripts` function in `lua_commands_test.js`
2. The script should use `game.print("SUCCESS: ...")` to indicate success and `game.print("ERROR: ...")` to indicate failure
3. The test runner will count the number of successes and errors to determine if the test passed

## Troubleshooting

If the tests fail, check the output for error messages. Common issues include:

- Missing dependencies
- Incompatible Factorio version
- Errors in the Lua scripts

If you're having trouble with the tests, try running Factorio manually with the mod installed to see if there are any issues.
80 changes: 80 additions & 0 deletions test/downloadFactorio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use strict";
const { spawn } = require('child_process');
const { createWriteStream } = require('fs');
const fs = require('fs-extra');
const https = require('https');
const path = require('path');

// Factorio version to test with
const factorioVersion = process.env.FACTORIO_VERSION || '1.1.110';

const downloadFactorio = async () => {
const baseDir = path.join(__dirname, `factorio_${factorioVersion}`);
const tarballPath = path.join(__dirname, `factorio_${factorioVersion}.tar.xz`);
const downloadUrl = `https://factorio.com/get-download/${factorioVersion}/headless/linux64`;

console.log(`Downloading Factorio ${factorioVersion} from ${downloadUrl}`);

// The factorio executable will be in baseDir/factorio/bin/...
const factorioDir = path.join(baseDir, 'factorio');

if (await fs.pathExists(factorioDir)) {
console.log('Factorio directory already exists, skipping download');
return factorioDir;
}

await fs.ensureDir(baseDir);

// Download the tarball
await new Promise((resolve, reject) => {
const file = createWriteStream(tarballPath);
https.get(downloadUrl, (response) => {
if (response.statusCode === 302 || response.statusCode === 301) {
// Follow redirect
https.get(response.headers.location, (redirectResponse) => {
redirectResponse.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
}).on('error', reject);
} else {
response.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
}
}).on('error', reject);
});

console.log('Download complete, extracting...');

// Extract to the base directory - the archive already contains a 'factorio' folder
await new Promise((resolve, reject) => {
const extract = spawn('tar', ['xf', tarballPath, '-C', baseDir]);

extract.stdout?.on('data', (data) => {
console.log(`stdout: ${data}`);
});

extract.stderr?.on('data', (data) => {
console.error(`stderr: ${data}`);
});

extract.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`tar extraction failed with code ${code}`));
}
});
});

// Clean up the tarball
await fs.unlink(tarballPath);

console.log('Extraction complete');
return factorioDir;
};
exports.downloadFactorio = downloadFactorio;
Loading