Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .github/macos-ci-no-signing.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CODE_SIGNING_ALLOWED = NO
CODE_SIGNING_REQUIRED = NO
CODE_SIGN_IDENTITY =
DEVELOPMENT_TEAM =
PROVISIONING_PROFILE_SPECIFIER =
96 changes: 96 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: CI

on:
pull_request:
push:
branches:
- main

concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
macos-tests:
name: macOS Tests
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive

- name: Generate Secrets Sources
run: PROJECT_DIR="$GITHUB_WORKSPACE" ./buildscripts/updateSecrets.sh

- name: Select Xcode 26.3
run: sudo xcode-select -s /Applications/Xcode_26.3.app/Contents/Developer

- name: Run macOS Test Plan
shell: bash
run: |
set -euo pipefail

result_bundle="${RUNNER_TEMP}/NetNewsWire-macOS.xcresult"
rm -rf "$result_bundle"

xcodebuild \
-project NetNewsWire.xcodeproj \
-scheme NetNewsWire \
-xcconfig .github/macos-ci-no-signing.xcconfig \
-destination "platform=macOS,arch=arm64" \
OTHER_SWIFT_FLAGS='$(inherited) -Xfrontend -warn-long-function-bodies=650 -Xfrontend -warn-long-expression-type-checking=650' \
-resultBundlePath "$result_bundle" \
test | xcbeautify

- name: Upload macOS Result Bundle
if: failure()
uses: actions/upload-artifact@v4
with:
name: netnewswire-macos-xcresult
path: ${{ runner.temp }}/NetNewsWire-macOS.xcresult
if-no-files-found: warn
retention-days: 7

ios-simulator-tests:
name: iOS Simulator Tests
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive

- name: Generate Secrets Sources
run: PROJECT_DIR="$GITHUB_WORKSPACE" ./buildscripts/updateSecrets.sh

- name: Select Xcode 26.3
run: sudo xcode-select -s /Applications/Xcode_26.3.app/Contents/Developer

- name: Run iOS Test Plan
shell: bash
run: |
set -euo pipefail

result_bundle="${RUNNER_TEMP}/NetNewsWire-iOS.xcresult"
rm -rf "$result_bundle"

xcodebuild \
-project NetNewsWire.xcodeproj \
-scheme NetNewsWire-iOS \
-destination "platform=iOS Simulator,name=iPhone 17" \
OTHER_SWIFT_FLAGS='$(inherited) -DDEBUG -DSKIP_APP_GROUP_ACCESS -Xfrontend -warn-long-function-bodies=650 -Xfrontend -warn-long-expression-type-checking=650' \
-resultBundlePath "$result_bundle" \
test | xcbeautify

- name: Upload iOS Result Bundle
if: failure()
uses: actions/upload-artifact@v4
with:
name: netnewswire-ios-xcresult
path: ${{ runner.temp }}/NetNewsWire-iOS.xcresult
if-no-files-found: warn
retention-days: 7
7 changes: 6 additions & 1 deletion NetNewsWire.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
519CA8E525841DB700EB079A /* CrashReporter in Frameworks */ = {isa = PBXBuildFile; productRef = 519CA8E425841DB700EB079A /* CrashReporter */; };
51BC2F3824D3439A00E90810 /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F3724D3439A00E90810 /* Account */; };
51C4CFF624D37DD500AF9874 /* Secrets in Frameworks */ = {isa = PBXBuildFile; productRef = 51C4CFF524D37DD500AF9874 /* Secrets */; };
84719F4C2EE01A1100EEF332 /* ActivityItemSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84719F4B2EE01A1100EEF332 /* ActivityItemSourceTests.swift */; };
840958632201629A002C1579 /* Subscribe to Feed.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
8424B3182DB73D4C0053AA11 /* RSParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8424B3172DB73D4C0053AA11 /* RSParser */; };
8424B3192DB73D4C0053AA11 /* RSParser in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 8424B3172DB73D4C0053AA11 /* RSParser */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
Expand Down Expand Up @@ -279,6 +280,7 @@
840D617C2029031C009BC708 /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetNewsWire.app; sourceTree = BUILT_PRODUCTS_DIR; };
844E47DC2E7DC72A0061A51A /* CODE_OF_CONDUCT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CODE_OF_CONDUCT.md; sourceTree = "<group>"; };
845B14A51FC2299E0013CF92 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
84719F4B2EE01A1100EEF332 /* ActivityItemSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tests/NetNewsWire-iOSTests/ActivityItemSourceTests.swift"; sourceTree = SOURCE_ROOT; };
848CEF1E2DB74B56002B35B5 /* NetNewsWire-iOS.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "NetNewsWire-iOS.xctestplan"; sourceTree = "<group>"; };
848E84CA2DB743FF0023F3BA /* NetNewsWire.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = NetNewsWire.xctestplan; sourceTree = "<group>"; };
849C64601ED37A5D003D8FC0 /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetNewsWire.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -340,6 +342,8 @@
84719F272DB9C52B00EEF332 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
NetNewsWire-iOSTests,
"NetNewsWire-iOSTests/ActivityItemSourceTests.swift",
"NetNewsWire-iOSTests/Info.plist",
NetNewsWireTests/Info.plist,
);
Expand Down Expand Up @@ -501,7 +505,7 @@
84719F372DB9C60400EEF332 /* xcconfig */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84719F392DB9C60500EEF332 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (common, ); path = xcconfig; sourceTree = "<group>"; };
84A6CFB52D1B4EC500F23315 /* iOS */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84A6D03F2D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84A6D0402D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84A6D0412D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = iOS; sourceTree = "<group>"; };
84CB35042DB9B5E2002AC251 /* Modules */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Modules; sourceTree = "<group>"; };
84D35D422DB9F32D004AA60E /* Shared */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84D35E0A2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0B2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0C2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0D2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0E2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0F2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Shared; sourceTree = "<group>"; };
84D35D422DB9F32D004AA60E /* Shared */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84D35E0A2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0B2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0C2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0D2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0E2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84D35E0F2DB9F32D004AA60E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = ("Resources/Appanoose.nnwtheme", "Resources/Hyperlegible.nnwtheme", "Resources/NewsFax.nnwtheme", "Resources/Promenade.nnwtheme", "Resources/Sepia.nnwtheme", ); path = Shared; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -1251,6 +1255,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84719F4C2EE01A1100EEF332 /* ActivityItemSourceTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
58 changes: 58 additions & 0 deletions Tests/NetNewsWire-iOSTests/ActivityItemSourceTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// ActivityItemSourceTests.swift
// NetNewsWire-iOSTests
//
// Created by Codex on 3/11/26.
//

import UIKit
import XCTest
@testable import NetNewsWire

@MainActor final class ActivityItemSourceTests: XCTestCase {

func testTitleItemSourceReturnsTitleForSupportedActivity() {
let source = TitleActivityItemSource(title: "Test Title")

let item = source.activityViewController(makeActivityViewController(), itemForActivityType: UIActivity.ActivityType(rawValue: "com.buffer.buffer.Buffer"))

XCTAssertEqual(item as? String, "Test Title")
}

func testTitleItemSourceReturnsNullForUnsupportedActivity() {
let source = TitleActivityItemSource(title: "Test Title")

let item = source.activityViewController(makeActivityViewController(), itemForActivityType: .postToFacebook)

XCTAssertTrue(item is NSNull)
}

func testTitleItemSourceReturnsNullWhenTitleIsMissing() {
let source = TitleActivityItemSource(title: nil)

let item = source.activityViewController(makeActivityViewController(), itemForActivityType: UIActivity.ActivityType(rawValue: "com.buffer.buffer.Buffer"))

XCTAssertTrue(item is NSNull)
}

func testArticleActivityItemSourceReturnsURLAndSubject() {
let url = URL(string: "https://netnewswire.com/story")!
let source = ArticleActivityItemSource(url: url, subject: "Subject")
let activityViewController = makeActivityViewController()

XCTAssertEqual(source.activityViewControllerPlaceholderItem(activityViewController) as? URL, url)
XCTAssertEqual(source.activityViewController(activityViewController, itemForActivityType: nil) as? URL, url)
XCTAssertEqual(source.activityViewController(activityViewController, subjectForActivityType: nil), "Subject")
}

func testArticleActivityItemSourceFallsBackToEmptySubject() {
let source = ArticleActivityItemSource(url: URL(string: "https://netnewswire.com/story")!, subject: nil)

XCTAssertEqual(source.activityViewController(makeActivityViewController(), subjectForActivityType: nil), "")
}

private func makeActivityViewController() -> UIActivityViewController {
UIActivityViewController(activityItems: [URL(string: "https://netnewswire.com")!], applicationActivities: nil)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- this script just tests that no error was generated from the script
try
tell application "NetNewsWire"
name of every folder of every account
name of folders of every account

Check failure on line 5 in Tests/NetNewsWireTests/ScriptingTests/scripts/testNameOfEveryFolder.applescript

View workflow job for this annotation

GitHub Actions / macOS Tests

Expected class name but found identifier. (-2741)
end tell
on error message
return {test_result:false, script_result:message}
Expand Down
14 changes: 9 additions & 5 deletions buildscripts/updateSecrets.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#!/bin/bash
set -euo pipefail

find "${PROJECT_DIR}" -name '*.gyb' |
while read file; do
echo "Generating ${file%.gyb}";
"${PROJECT_DIR}/buildscripts/gyb" --line-directive '' -o "${file%.gyb}" "$file";
done
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${PROJECT_DIR:-$(cd "${SCRIPT_DIR}/.." && pwd)}"

find "${PROJECT_ROOT}" -name '*.gyb' -print0 |
while IFS= read -r -d '' file; do
echo "Generating ${file%.gyb}"
"${PROJECT_ROOT}/buildscripts/gyb" --line-directive '' -o "${file%.gyb}" "$file"
done
2 changes: 2 additions & 0 deletions xcconfig/NetNewsWire_iOSTests_target.xcconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "./common/NetNewsWire_ios_target_common.xcconfig"
#include "./common/NetNewsWire_codesigning_common.xcconfig"

BUNDLE_LOADER = $(TEST_HOST)
Expand All @@ -7,3 +8,4 @@ LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_pa
PRODUCT_BUNDLE_IDENTIFIER = $(ORGANIZATION_IDENTIFIER).NetNewsWire-iOSTests
PRODUCT_NAME = $(TARGET_NAME)
SUPPORTED_PLATFORMS = iphoneos iphonesimulator
TEST_HOST = $(BUILT_PRODUCTS_DIR)/NetNewsWire.app/NetNewsWire
Loading