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
77 changes: 41 additions & 36 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,60 @@ name: Test Get WordPress Versions Action

on:
push:
branches: [ main ]
branches: [ develop ]
pull_request:
branches: [ main ]
branches: [ develop ]
workflow_dispatch:

jobs:
test-action:
runs-on: ubuntu-latest
outputs:
versions: ${{ steps.get-versions.outputs.versions }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Get WordPress Versions (default)
- name: Get WordPress Versions
id: get-versions
uses: ./
with:
number: 3

- name: Display versions
- name: Test Action Output
run: |
echo "WordPress versions: ${{ steps.get-versions.outputs.versions }}"
echo "Number of versions: $(echo '${{ steps.get-versions.outputs.versions }}' | jq length)"

test-with-custom-number:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Get WordPress Versions (5 versions)
id: get-versions-5
uses: ./
with:
number: 5

- name: Display versions
run: |
echo "WordPress versions (5): ${{ steps.get-versions-5.outputs.versions }}"

test-matrix-strategy:
needs: test-action
runs-on: ubuntu-latest
strategy:
matrix:
wp-version: ${{ fromJson(needs.test-action.outputs.versions) }}
steps:
- name: Test with WordPress ${{ matrix.wp-version }}
run: |
echo "Testing with WordPress version: ${{ matrix.wp-version }}"
echo "This would be where you run tests against this version"
# Get the versions output
versions='${{ steps.get-versions.outputs.versions }}'
echo "WordPress versions: $versions"

# Test that output is valid JSON
if ! echo "$versions" | jq . > /dev/null 2>&1; then
echo "❌ ERROR: Output is not valid JSON"
exit 1
fi
echo "✅ Output is valid JSON"

# Test that we got exactly 3 versions (as requested)
count=$(echo "$versions" | jq length)
if [ "$count" -ne 3 ]; then
echo "❌ ERROR: Expected 3 versions, got $count"
exit 1
fi
echo "✅ Got expected number of versions: $count"

# Test that all versions are strings and match the pattern (e.g., "6.4", "6.3")
if ! echo "$versions" | jq -e 'all(type == "string" and test("^[0-9]+\\.[0-9]+$"))' > /dev/null; then
echo "❌ ERROR: Not all versions match expected format (e.g., '6.4')"
exit 1
fi
echo "✅ All versions match expected format"

# Test that versions are in descending order
sorted_versions=$(echo "$versions" | jq -c 'sort_by(. | split(".") | map(tonumber)) | reverse')
if [ "$versions" != "$sorted_versions" ]; then
echo "❌ ERROR: Versions are not in descending order"
echo "Expected: $sorted_versions"
echo "Actual: $versions"
exit 1
fi
echo "✅ Versions are in descending order"

echo "🎉 All tests passed!"
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ runs:
with:
script: |
const getWordPressVersions = require('./get-versions.js');
await getWordPressVersions();
const inputNumber = '${{ inputs.number }}';
const parsedNumber = parseInt(inputNumber);
const numberOfVersions = inputNumber === '' || isNaN(parsedNumber) ? 3 : parsedNumber;
await getWordPressVersions(core, numberOfVersions);
5 changes: 1 addition & 4 deletions get-versions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
const core = require('@actions/core');

async function getWordPressVersions() {
const numberOfVersions = parseInt(core.getInput('number')) || 3;
async function getWordPressVersions(core, numberOfVersions = 3) {

try {
// Fetch WordPress version data from the API
Expand Down
107 changes: 38 additions & 69 deletions get-versions.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
const getWordPressVersions = require('./get-versions');

// Mock @actions/core
// Mock core object
const mockCore = {
getInput: jest.fn(),
setOutput: jest.fn(),
setFailed: jest.fn(),
};

jest.mock('@actions/core', () => mockCore);
const getWordPressVersions = require('./get-versions');

// Mock global fetch
global.fetch = jest.fn();
Expand All @@ -16,91 +13,73 @@ describe('getWordPressVersions', () => {
beforeEach(() => {
jest.clearAllMocks();
console.log = jest.fn(); // Mock console.log
fetch.mockClear(); // Clear fetch mock
});

describe('successful API response', () => {
const mockApiResponse = {
offers: [
{ version: '6.4.1', response: 'autoupdate' },
{ version: '6.4.0', response: 'autoupdate' },
{ version: '6.3.2', response: 'autoupdate' },
{ version: '6.3.1', response: 'autoupdate' },
{ version: '6.3.0', response: 'autoupdate' },
{ version: '6.2.3', response: 'autoupdate' },
{ version: '6.2.2', response: 'autoupdate' },
{ version: '6.1.4', response: 'autoupdate' },
{ version: '5.9.8', response: 'upgrade' }, // Should be filtered out
{ version: '5.9.8', response: 'autoupdate' },
{ version: '5.8.7', response: 'autoupdate' },
{ version: '5.7.9', response: 'upgrade' }, // Should be filtered out
]
};

beforeEach(() => {
it('should fetch and return default number of versions (3)', async () => {
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(mockApiResponse),
});
});

it('should fetch and return default number of versions (3)', async () => {
mockCore.getInput.mockReturnValue('');

await getWordPressVersions();
await getWordPressVersions(mockCore, 3);

expect(fetch).toHaveBeenCalledWith('https://api.wordpress.org/core/version-check/1.7/');
expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3', '6.2']));
expect(mockCore.setFailed).not.toHaveBeenCalled();
});

it('should fetch and return custom number of versions', async () => {
mockCore.getInput.mockReturnValue('5');
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(mockApiResponse),
});

await getWordPressVersions();
await getWordPressVersions(mockCore, 5);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3', '6.2', '6.1', '5.9']));
});

it('should handle string input for number', async () => {
mockCore.getInput.mockReturnValue('2');
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(mockApiResponse),
});

await getWordPressVersions();
await getWordPressVersions(mockCore, 2);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3']));
});

it('should handle invalid number input and default to 3', async () => {
mockCore.getInput.mockReturnValue('invalid');
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(mockApiResponse),
});

await getWordPressVersions();
await getWordPressVersions(mockCore, 3);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3', '6.2']));
});

it('should filter out non-autoupdate versions', async () => {
mockCore.getInput.mockReturnValue('10');

await getWordPressVersions();

const expectedVersions = ['6.4', '6.3', '6.2', '6.1'];
expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(expectedVersions));
});

it('should remove duplicate versions after patch removal', async () => {
const duplicateResponse = {
offers: [
{ version: '6.4.2', response: 'autoupdate' },
{ version: '6.4.1', response: 'autoupdate' },
{ version: '6.4.0', response: 'autoupdate' },
{ version: '6.3.1', response: 'autoupdate' },
]
};

fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(duplicateResponse),
json: jest.fn().mockResolvedValue(mockApiResponse),
});

mockCore.getInput.mockReturnValue('3');
await getWordPressVersions(mockCore, 10);

await getWordPressVersions();

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3']));
const expectedVersions = ['6.4', '6.3', '6.2', '6.1', '5.9', '5.8'];
expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(expectedVersions));
});

it('should sort versions correctly', async () => {
Expand All @@ -117,17 +96,17 @@ describe('getWordPressVersions', () => {
json: jest.fn().mockResolvedValue(unsortedResponse),
});

mockCore.getInput.mockReturnValue('4');

await getWordPressVersions();
await getWordPressVersions(mockCore, 4);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3', '6.2', '6.1']));
});

it('should log the found versions', async () => {
mockCore.getInput.mockReturnValue('2');
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(mockApiResponse),
});

await getWordPressVersions();
await getWordPressVersions(mockCore, 2);

expect(console.log).toHaveBeenCalledWith('Found 2 WordPress versions:', ['6.4', '6.3']);
});
Expand All @@ -137,9 +116,8 @@ describe('getWordPressVersions', () => {
it('should handle fetch errors', async () => {
const fetchError = new Error('Network error');
fetch.mockRejectedValue(fetchError);
mockCore.getInput.mockReturnValue('3');

await getWordPressVersions();
await getWordPressVersions(mockCore, 3);

expect(mockCore.setFailed).toHaveBeenCalledWith('Failed to fetch WordPress versions: Network error');
expect(mockCore.setOutput).not.toHaveBeenCalled();
Expand All @@ -149,9 +127,8 @@ describe('getWordPressVersions', () => {
fetch.mockResolvedValue({
json: jest.fn().mockRejectedValue(new Error('Invalid JSON')),
});
mockCore.getInput.mockReturnValue('3');

await getWordPressVersions();
await getWordPressVersions(mockCore, 3);

expect(mockCore.setFailed).toHaveBeenCalledWith('Failed to fetch WordPress versions: Invalid JSON');
});
Expand All @@ -160,9 +137,8 @@ describe('getWordPressVersions', () => {
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue({ someOtherData: 'test' }),
});
mockCore.getInput.mockReturnValue('3');

await getWordPressVersions();
await getWordPressVersions(mockCore, 3);

expect(mockCore.setFailed).toHaveBeenCalledWith('No version offers found in WordPress API response');
});
Expand All @@ -171,9 +147,8 @@ describe('getWordPressVersions', () => {
fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue({ offers: [] }),
});
mockCore.getInput.mockReturnValue('3');

await getWordPressVersions();
await getWordPressVersions(mockCore, 3);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify([]));
});
Expand All @@ -192,27 +167,23 @@ describe('getWordPressVersions', () => {
json: jest.fn().mockResolvedValue(smallResponse),
});

mockCore.getInput.mockReturnValue('5');

await getWordPressVersions();
await getWordPressVersions(mockCore, 5);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.4', '6.3']));
});

it('should handle zero as input', async () => {
const mockApiResponse = {
const mockResponse = {
offers: [
{ version: '6.4.1', response: 'autoupdate' },
]
};

fetch.mockResolvedValue({
json: jest.fn().mockResolvedValue(mockApiResponse),
json: jest.fn().mockResolvedValue(mockResponse),
});

mockCore.getInput.mockReturnValue('0');

await getWordPressVersions();
await getWordPressVersions(mockCore, 0);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify([]));
});
Expand All @@ -231,9 +202,7 @@ describe('getWordPressVersions', () => {
json: jest.fn().mockResolvedValue(complexVersionResponse),
});

mockCore.getInput.mockReturnValue('4');

await getWordPressVersions();
await getWordPressVersions(mockCore, 4);

expect(mockCore.setOutput).toHaveBeenCalledWith('versions', JSON.stringify(['6.10', '6.9', '6.2']));
});
Expand Down
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
},
"dependencies": {
"@actions/core": "^1.10.0"
},
"devDependencies": {
"jest": "^29.7.0"
},
Expand Down