# frozen_string_literal: true # ------------------------------------ # # Jazzy Integration tests # # ------------------------------------ # #-----------------------------------------------------------------------------# # The following integrations tests are based on file comparison. # # 1. For each test there is a folder with a `before` and `after` subfolders. # 2. The contents of the before folder are copied to the `TMP_DIR` folder and # then the given arguments are passed to the `JAZZY_BINARY`. # 3. After the jazzy command completes the execution the each file in the # `after` subfolder is compared to the contents of the temporary # directory. If the contents of the file do not match an error is # registered. # # Notes: # # - The output of the jazzy command is saved in the `execution_output.txt` file # which should be added to the `after` folder to test the Jazzy UI. # - To create a new test, just create a before folder with the environment to # test, copy it to the after folder and run the tested pod command inside. # Then just add the tests below this files with the name of the folder and # the arguments. # # Rationale: # # - Have a way to track precisely the evolution of the artifacts (and of the # UI) produced by jazzy (git diff of the after folders). # - Allow uses to submit pull requests with the environment necessary to # reproduce an issue. # - Have robust tests which don't depend on the programmatic interface of # Jazzy. These tests depend only the binary and its arguments an thus are # suitable for testing Jazzy regardless of the implementation (they could even # work for a Swift one) #-----------------------------------------------------------------------------# # @return [Pathname] The root of the repo. # ROOT = Pathname.new(File.expand_path('..', __dir__)) unless defined? ROOT $:.unshift((ROOT + 'spec').to_s) require 'rubygems' require 'bundler/setup' require 'pretty_bacon' require 'colored2' require 'CLIntegracon' require 'cocoapods' def configure_cocoapods Pod::Config.instance.with_changes(silent: true) do Pod::Command::Setup.invoke Pod::Command::Repo::AddCDN.invoke(%w[trunk https://cdn.cocoapods.org/]) Pod::Command::Repo::Update.invoke(%w[trunk]) end end CLIntegracon.configure do |c| c.spec_path = ROOT + 'spec/integration_specs' c.temp_path = ROOT + 'tmp' # Ignore certain OSX files c.ignores '.DS_Store' c.ignores '.git' c.ignores %r{^(?!((api-)?docs(/|\z)|execution_output.txt))} c.ignores '**/*.tgz' # Remove absolute paths from output c.transform_produced '**/undocumented.json' do |path| File.write( path, File.read(path).gsub( c.temp_path.to_s, '', ).gsub( c.spec_path.to_s, '', ).gsub( '/transformed', '', ), ) end # Transform produced databases to csv c.transform_produced '**/*.dsidx' do |path| File.write("#{path}.csv", `sqlite3 -header -csv #{path} "select * from searchIndex;"`) end # Now that we're comparing the CSV, we don't care about the binary c.ignores '**/*.dsidx' c.hook_into :bacon end describe_cli 'jazzy' do subject do |s| s.executable = "ruby #{ROOT + 'bin/jazzy'}" s.environment_vars = { 'JAZZY_FAKE_DATE' => 'YYYY-MM-DD', 'JAZZY_FAKE_VERSION' => 'X.X.X', 'COCOAPODS_SKIP_UPDATE_MESSAGE' => 'TRUE', 'JAZZY_INTEGRATION_SPECS' => 'TRUE', 'JAZZY_FAKE_MODULE_VERSION' => 'Y.Y.Y', } s.default_args = [] s.replace_path ROOT.to_s, 'ROOT' s.replace_pattern /^[\d\s:.-]+ ruby\[\d+:\d+\] warning:.*$\n?/, '' # Remove version numbers from CocoaPods dependencies # to make specs resilient against dependency updates. s.replace_pattern(/(Installing \w+ )\((.*)\)/, '\1(X.Y.Z)') # Xcode 13.3 etc workaround s.replace_pattern(/202[\d.:\- ]+xcodebuild.*?\n/, '') # Xcode 14 / in-proc sourcekitd workaround s.replace_pattern(/:0: remark.*?\n/, '') # CLIntegracon 0.8 s.replace_pattern(%r{/transformed/}, '/') # Xcode 15 workaround s.replace_pattern(/objc\[.....\]: Class _?DTX\w+ is implemented in both.*?\n/, '') # arm vs. intel workaround s.replace_pattern(%r{(?<=build/)(arm64|x86_64)(?=-apple)}, '') end require 'shellwords' realm_head = <<-HTML HTML realm_jazzy_yaml = <<-YAML build_tool_arguments: - "-scheme" - "RealmSwift" - "SWIFT_VERSION=4.2" - "-destination" - "platform=OS X,arch=x86_64" YAML spec_subset = ENV.fetch('JAZZY_SPEC_SUBSET', nil) # rubocop:disable Style/MultilineIfModifier describe 'jazzy objective-c' do describe 'Creates Realm Objective-C docs' do realm_version = '' relative_path = 'spec/integration_specs/document_realm_objc/before' Dir.chdir(ROOT + relative_path) do realm_version = `./build.sh get-version`.chomp # jazzy will fail if it can't find all public header files `touch Realm/RLMPlatform.h` end behaves_like cli_spec 'document_realm_objc', '--objc ' \ '--author Realm ' \ '--author_url "https://realm.io" ' \ '--source-host-url ' \ 'https://github.com/realm/realm-cocoa ' \ '--source-host-files-url https://github.com/realm/' \ "realm-cocoa/tree/v#{realm_version} " \ '--module Realm ' \ "--module-version #{realm_version} " \ '--root-url https://realm.io/docs/objc/' \ "#{realm_version}/api/ " \ '--umbrella-header Realm/Realm.h ' \ '--framework-root . ' \ "--head #{realm_head.shellescape}" end describe 'Creates docs for ObjC-Swift project with a variety of contents' do base = ROOT + 'spec/integration_specs/misc_jazzy_objc_features/before' Dir.chdir(base) do sourcekitten = ROOT + 'bin/sourcekitten' sdk = `xcrun --show-sdk-path --sdk iphonesimulator`.chomp objc_args = "#{base}/MiscJazzyObjCFeatures/MiscJazzyObjCFeatures.h " \ '-- -x objective-c ' \ "-isysroot #{sdk} " \ "-I #{base} " \ '-fmodules' `#{sourcekitten} doc --objc #{objc_args} > objc.json` `#{sourcekitten} doc -- clean build > swift.json` end behaves_like cli_spec 'misc_jazzy_objc_features', '--theme fullwidth ' \ '-s objc.json,swift.json' end end if !spec_subset || spec_subset == 'objc' describe 'jazzy swift' do describe 'Creates docs with a module name, author name, project URL, ' \ 'xcodebuild options, and github info' do behaves_like cli_spec 'document_alamofire', '--skip-undocumented ' \ '--clean ' \ '--xcodebuild-arguments ' \ "-destination,'platform=OS X'" end describe 'Creates Realm Swift docs' do realm_version = '' realm_path = ROOT + 'spec/integration_specs/document_realm_swift/before' realm_jazzy_path = realm_path + '.jazzy.yaml' Dir.chdir(realm_path) do realm_version = `./build.sh get-version`.chomp end # Xcode 16 workaround File.write(realm_jazzy_path, realm_jazzy_yaml) behaves_like cli_spec 'document_realm_swift', '--author Realm ' \ '--author_url "https://realm.io" ' \ '--source-host-url ' \ 'https://github.com/realm/realm-cocoa ' \ '--source-host-files-url https://github.com/realm/' \ "realm-cocoa/tree/v#{realm_version} " \ '--module RealmSwift ' \ "--module-version #{realm_version} " \ '--root-url https://realm.io/docs/swift/' \ "#{realm_version}/api/ " \ "--head #{realm_head.shellescape}" FileUtils.rm_rf realm_jazzy_path end describe 'Creates Siesta docs' do # Siesta already has Docs/ # Use the default Swift version rather than the specified 4.0 behaves_like cli_spec 'document_siesta', '--output api-docs ' \ '--swift-version= ' end describe 'Creates docs for Swift project with a variety of contents' do behaves_like cli_spec 'misc_jazzy_features' end describe 'Creates docs for Swift project from a .swiftmodule' do build_path = Dir.getwd + '/tmp/.build' package_path = ROOT + 'spec/integration_specs/misc_jazzy_symgraph_features/before' `swift build --package-path #{package_path} --scratch-path #{build_path}` module_path = `swift build --scratch-path #{build_path} --show-bin-path` behaves_like cli_spec 'misc_jazzy_symgraph_features', '--swift-build-tool symbolgraph ' \ '--build-tool-arguments ' \ '-emit-extension-block-symbols,-I,' \ "#{module_path.chomp}/Modules" end describe 'Creates docs for a multiple-module project' do behaves_like cli_spec 'jazzy_multi_modules' end end if !spec_subset || spec_subset == 'swift' describe 'jazzy cocoapods' do # Xcode 14.3 workaround, special podspec podspec_patch = ROOT + 'spec/Moya.podspec' podspec_used = ROOT + 'spec/integration_specs/document_moya_podspec/before/Moya.podspec' podspec_save = ROOT + 'spec/Moya.podspec.safe' FileUtils.cp_r podspec_used, podspec_save, remove_destination: true FileUtils.cp_r podspec_patch, podspec_used, remove_destination: true configure_cocoapods describe 'Creates docs for a podspec with dependencies and subspecs' do behaves_like cli_spec 'document_moya_podspec', '--podspec=Moya.podspec' end FileUtils.cp_r podspec_save, podspec_used, remove_destination: true FileUtils.rm_rf podspec_save end if !spec_subset || spec_subset == 'cocoapods' # rubocop:enable Style/MultilineIfModifier end