Repository: jekyll/jekyll (Ruby)

Issue:
[Bug]: CI Appveyor 2.7 builds fail
### Operating System

Windows

### Ruby Version

Environment: RUBY_FOLDER_VER=27, TZINFO_VERSION=~> 1.2, TEST_SUITE=test

### Jekyll Version

jekyll 4.3.3

### GitHub Pages Version

Latest

### Expected Behavior

I expected a green build, perhaps only using non-EOL'd Ruby versions.

### Current Behavior

https://ci.appveyor.com/project/jekyll/jekyll/builds/50207910 uses a too-new Bundler (2.5.13) for it work.

### Relevant log output

```shell
bundle install --retry 5 --jobs=%NUMBER_OF_PROCESSORS%
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:35: warning: already initialized constant Bundler::CompactIndexClient::SUPPORTED_DIGESTS
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:35: warning: previous definition of SUPPORTED_DIGESTS was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:36: warning: already initialized constant Bundler::CompactIndexClient::DEBUG_MUTEX
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:36: warning: previous definition of DEBUG_MUTEX was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:39: warning: already initialized constant Bundler::CompactIndexClient::INFO_NAME
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:39: warning: previous definition of INFO_NAME was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:40: warning: already initialized constant Bundler::CompactIndexClient::INFO_VERSION
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:40: warning: previous definition of INFO_VERSION was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:41: warning: already initialized constant Bundler::CompactIndexClient::INFO_PLATFORM
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:41: warning: previous definition of INFO_PLATFORM was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:42: warning: already initialized constant Bundler::CompactIndexClient::INFO_DEPS
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:42: warning: previous definition of INFO_DEPS was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:43: warning: already initialized constant Bundler::CompactIndexClient::INFO_REQS
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:43: warning: previous definition of INFO_REQS was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:35: warning: already initialized constant Bundler::CompactIndexClient::SUPPORTED_DIGESTS
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:35: warning: previous definition of SUPPORTED_DIGESTS was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:36: warning: already initialized constant Bundler::CompactIndexClient::DEBUG_MUTEX
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:36: warning: previous definition of DEBUG_MUTEX was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:39: warning: already initialized constant Bundler::CompactIndexClient::INFO_NAME
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:39: warning: previous definition of INFO_NAME was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:40: warning: already initialized constant Bundler::CompactIndexClient::INFO_VERSION
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:40: warning: previous definition of INFO_VERSION was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:41: warning: already initialized constant Bundler::CompactIndexClient::INFO_PLATFORM
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:41: warning: previous definition of INFO_PLATFORM was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:42: warning: already initialized constant Bundler::CompactIndexClient::INFO_DEPS
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:42: warning: previous definition of INFO_DEPS was here
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:43: warning: already initialized constant Bundler::CompactIndexClient::INFO_REQS
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client.rb:43: warning: previous definition of INFO_REQS was here
--- ERROR REPORT TEMPLATE -------------------------------------------------------

SyntaxError: C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client/cache.rb:46: syntax error, unexpected '=', expecting ';' or '\n'
      def names_path = directory.join("names")
                     ^
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-2.5.13/lib/bundler/compact_index_client/cache.rb:47: syntax error, unexpected '=', expecting ';' or '\n'
```


### Code Sample

See https://ci.appveyor.com/project/jekyll/jekyll/builds/50207910 


Discussion: Hi,
Since there's a successful test run with Ruby 2.7 via GitHub Actions, we could consider doing away with AppVeyor entirely and add a couple of Windows-based jobs to the existing CI workflow.

(*Subject to approval of active maintainers here*)
> Since there's a successful test run with Ruby 2.7 via GitHub Actions

Do you have any links for that?  I'd like to see what test commands it was running.

JFYI, locally I tried running `bundle exec rake test` with Ruby head (some Gemfile changes due to Ruby 'bundled' gems), and there were only three failures, all are 'date/time' related.


```
957 tests, 2096 assertions, 3 failures, 0 errors, 13 skips

Failure:
TestDocument#test_: a document with a date with time but without timezone should return the expected date via Liquid.  [C:/Greg/GitHub/jekyll/test/test_document.rb:645]
Minitest::Assertion: Expected: "2015/10/01"
  Actual: "2015/09/30"

Failure:
TestDocument#test_: a document with a date with time but without timezone should have the expected date.  [C:/Greg/GitHub/jekyll/test/test_document.rb:641]
Minitest::Assertion: Expected: "2015/10/01"
  Actual: "2015/09/30"

Failure:
TestFilters#test_: filters jsonify filter should convert drop to json.  [C:/Greg/GitHub/jekyll/test/test_filters.rb:702]
Minitest::Assertion: Expected: {
  "name": "2008-02-02-published.markdown",
  "path": "_posts/2008-02-02-published.markdown",
  "previous": null,
  "output": null,
  "content": "This should be published.\n",
  "id": "/publish_test/2008/02/02/published",
  "url": "/publish_test/2008/02/02/published.html",
  "relative_path": "_posts/2008-02-02-published.markdown",
  "collection": "posts",
  "excerpt": "<p>This should be published.</p>\n",
  "draft": false,
  "categories": [
    "publish_test"
  ],
  "layout": "default",
  "title": "Publish",
  "category": "publish_test",
  "date": "2008-02-02 00:00:00 +0000",
  "slug": "published",
  "ext": ".markdown",
  "tags": [

  ]
}
  Actual: {
  "name": "2008-02-02-published.markdown",
  "excerpt": "<p>This should be published.</p>\n",
  "path": "_posts/2008-02-02-published.markdown",
  "content": "This should be published.\n",
  "id": "/publish_test/2008/02/02/published",
  "output": null,
  "collection": "posts",
  "title": "Publish",
  "tags": [

  ],
  "categories": [
    "publish_test"
  ],
  "relative_path": "_posts/2008-02-02-published.markdown",
  "date": "2008-02-02 00:00:00 -0600",
  "previous": null,
  "url": "/publish_test/2008/02/02/published.html",
  "draft": false,
  "layout": "default",
  "category": "publish_test",
  "slug": "published",
  "ext": ".markdown"
}
```

Last test I believe fails due to the different date strings, "2008-02-02 00:00:00 +0000" vs "2008-02-02 00:00:00 -0600".
Hello @MSP-Greg,

When I posted about a successful test run on GitHub Actions (GA) almost a month ago, I was referring to existing successful test runs (on Ubuntu images with Ruby 2.7) in this repo's workflows and not exactly a successful test run using a Windows image on GA.

I had recommended the move away from AppVeyor so that all CI runs of this repo could be managed from the same YAML file, using the same routines. (The current AppVeyor failures for this repo is due to having the pre-installed Bundler using Ruby 3.0 syntax even though the jobs ran on Ruby 2.7).

Regarding the failures (runs with ruby-head) you have highlighted, all of those are timezone related mismatch between (DST ??) Windows and posix and may need some fudging of test expectations.
https://github.com/rubygems/rubygems/blob/master/bundler/CHANGELOG.md#250-december-15-2023 bundler dropped Ruby 2.7 supports after this version, which breaks the Windows CI. Should we lock bundler version or drop 2.7 support either? @ashmaroli 
@crispgm https://github.com/ruby/setup-ruby/blob/master/action.yml#L20 setup-ruby offers a `bundler:` parameter, which can given to GHA Workflows, to "select a Bundler version".
Ruby 2.7 reached EOL about 18 months ago (2023-03-31). But I would like to test with it for *one more minor version of Jekyll*.
The crossroad here is between either continuing with AppVeyor or move Windows based testing to GitHub Actions as well.

(While the latter seems better to me owing to having the settings, logs and statuses all at same place, I would also like @mattr- and @parkr to weigh in on this)
I would vote to use only GitHub Actions where possible. I believe Jekyll 4 can informally drop Ruby 2.7 support by dropping the target in the test matrix, but I would not raise the required Ruby version in the gemspec until Jekyll 5.
So, a suggested next action is "make a PR that takes the AppVeyor steps as a "runs-on: windows-latest" + a few `includes` elements that has `os: windows-latest` in them.
Awesome! So, its two votes in favor of migrating to GitHub Actions.
@olleolleolle I will assign myself to this task if you haven't started working on this already. This is now high on the priority list.
@ashmaroli

> Regarding the failures (runs with ruby-head) you have highlighted, all of those are timezone related mismatch between (DST ??) Windows and posix and may need some fudging of test expectations.

I just looked at the bash test script, and it contains the following, which explains the test failures:
```bash
# Tests only pass when timezone offset is zero.
TZ=UTC
```

Re some of the 'Bundler' discussion, I've found that updating RubyGems with older Rubies works better than just updating Bundler, and works with Rubies going back to 2.4 (I think).  `setup-ruby` also has an input for it.

Also, I generally don't like to run Windows CI in a bash shell.  There are certainly repos doing it, but it often brings a set of problems that are difficult to address.
Thank you for sharing your insights, @MSP-Greg



Fix (patch):
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index a6f9434cb94..3077f286f1c 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -65,8 +65,6 @@
 # @jekyll/stability
 Gemfile                              @jekyll/stability
 *.gemspec                            @jekyll/stability
-.travis.yml                          @jekyll/stability
-appveyor.yml                         @jekyll/stability
 /lib/jekyll/configuration.rb         @jekyll/stability
 /lib/jekyll/deprecator.rb            @jekyll/stability
 /lib/jekyll/frontmatter_defaults.rb  @jekyll/stability
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8ca6ee66a66..138ab08808d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,27 +12,28 @@ on:
 
 jobs:
   ci:
-    name: "Run Tests (${{ matrix.label }})"
-    runs-on: "ubuntu-latest"
+    name: "Run Tests (${{ matrix.ruby.label }} on ${{ matrix.os.label }})"
+    runs-on: ${{ matrix.os.image }}
     strategy:
       fail-fast: false
       matrix:
-        include:
+        ruby:
           - label: Ruby 2.7
-            ruby_version: "2.7"
-          - label: Ruby 3.0
-            ruby_version: "3.0"
-          - label: Ruby 3.1
-            ruby_version: "3.1"
-          - label: Ruby 3.2
-            ruby_version: "3.2"
+            version: "2.7"
+          - label: Ruby 3.3
+            version: "3.3"
+        os:
+          - label: Linux
+            image: "ubuntu-latest"
+          - label: Windows
+            image: "windows-latest"
     steps:
       - name: Checkout Repository
         uses: actions/checkout@v4
-      - name: "Set up ${{ matrix.label }}"
+      - name: "Set up ${{ matrix.ruby.label }}"
         uses: ruby/setup-ruby@v1
         with:
-          ruby-version: ${{ matrix.ruby_version }}
+          ruby-version: ${{ matrix.ruby.version }}
           bundler-cache: true
       - name: Run Minitest based tests
         run: bash script/test
diff --git a/README.markdown b/README.markdown
index ad55a2f3321..81b30328da2 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,8 +1,7 @@
 # [Jekyll](https://jekyllrb.com/)
 
 [![Gem Version](https://img.shields.io/gem/v/jekyll.svg)][ruby-gems]
-[![Linux Build Status](https://github.com/jekyll/jekyll/workflows/Continuous%20Integration/badge.svg)][ci-workflow]
-[![Windows Build status](https://img.shields.io/appveyor/ci/jekyll/jekyll/master.svg?label=Windows%20build)][appveyor]
+[![Build Status](https://github.com/jekyll/jekyll/workflows/Continuous%20Integration/badge.svg)][ci-workflow]
 [![Backers on Open Collective](https://opencollective.com/jekyll/backers/badge.svg)](#backers)
 [![Sponsors on Open Collective](https://opencollective.com/jekyll/sponsors/badge.svg)](#sponsors)
 
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index d37c277bbf6..00000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-version: "{build}"
-image: Visual Studio 2019
-build: off
-
-clone_depth: 5
-
-branches:
-  only:
-    - master
-    - themes
-    - /.*-stable$/
-
-environment:
-  BUNDLE_WITHOUT: "benchmark:development"
-  matrix:
-    - RUBY_FOLDER_VER: "27"
-      TZINFO_VERSION: "~> 1.2"
-      TEST_SUITE: "test"
-    - RUBY_FOLDER_VER: "27"
-      TZINFO_VERSION: "~> 2.0"
-      TEST_SUITE: "test"
-    - RUBY_FOLDER_VER: "27"
-      TEST_SUITE: "default-site"
-    - RUBY_FOLDER_VER: "27"
-      TEST_SUITE: "profile-docs"
-    - RUBY_FOLDER_VER: "27"
-      TEST_SUITE: "memprof"
-    - RUBY_FOLDER_VER: "27"
-      TZINFO_VERSION: "~> 1.2"
-      TEST_SUITE: "cucumber"
-    - RUBY_FOLDER_VER: "27"
-      TZINFO_VERSION: "~> 2.0"
-      TEST_SUITE: "cucumber"
-
-install:
-  - SET PATH=C:\Ruby%RUBY_FOLDER_VER%-x64\bin;%PATH%
-  - bundle config set --local clean 'true'
-  - bundle config set --local path 'vendor\bundle'
-  - bundle install --retry 5 --jobs=%NUMBER_OF_PROCESSORS%
-
-test_script:
-  - ruby --version
-  - gem --version
-  - bundler --version
-  - bash ./script/cibuild
-
-cache:
-  # If one of the files after the right arrow changes, cache will be invalidated
-  - 'vendor\bundle -> appveyor.yml,Gemfile,jekyll.gemspec'
diff --git a/features/collections.feature b/features/collections.feature
index 8b8813b607f..8e3f482b24e 100644
--- a/features/collections.feature
+++ b/features/collections.feature
@@ -82,8 +82,8 @@ Feature: Collections
     When I run jekyll build
     Then I should get a zero exit status
     Then the _site directory should exist
-    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" unless Windows
-    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if on Windows
+    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" if platform supports symlinks
+    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if platform does not support symlinks
 
   Scenario: Collections specified as an hash
     Given I have an "index.html" page that contains "Collections: {% for method in site.methods %}{{ method.relative_path }} {% endfor %}"
@@ -96,8 +96,8 @@ Feature: Collections
     When I run jekyll build
     Then I should get a zero exit status
     Then the _site directory should exist
-    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" unless Windows
-    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if on Windows
+    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" if platform supports symlinks
+    And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if platform does not support symlinks
 
   Scenario: Rendered collection with document with future date
     Given I have a _puppies directory
@@ -377,8 +377,8 @@ Feature: Collections
     When I run jekyll build
     Then I should get a zero exit status
     Then the _site directory should exist
-    And I should see "All documents: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" unless Windows
-    And I should see "All documents: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if on Windows
+    And I should see "All documents: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" if platform supports symlinks
+    And I should see "All documents: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if platform does not support symlinks
 
   Scenario: Documents have an output attribute, which is the converted HTML
     Given I have an "index.html" page that contains "Second document's output: {{ site.documents[2].output }}"
@@ -432,8 +432,8 @@ Feature: Collections
     When I run jekyll build
     Then I should get a zero exit status
     And the _site directory should exist
-    And I should see "2. of 10: <p>Page without title.</p>" in "_site/index.html" unless Windows
-    And I should see "2. of 9: <p>Page without title.</p>" in "_site/index.html" if on Windows
+    And I should see "2. of 10: <p>Page without title.</p>" in "_site/index.html" if platform supports symlinks
+    And I should see "2. of 9: <p>Page without title.</p>" in "_site/index.html" if platform does not support symlinks
 
   Scenario: Sort by relative_path
     Given I have an "index.html" page that contains "Collections: {% assign methods = site.methods | sort: 'relative_path' %}{{ methods | map:"title" | join: ", " }}"
@@ -446,8 +446,8 @@ Feature: Collections
     When I run jekyll build
     Then I should get a zero exit status
     Then the _site directory should exist
-    And I should see "Collections: this is a test!, Collection#entries, Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, Initialize, Ellipsis Path, Site#generate, YAML with Dots" in "_site/index.html" unless Windows
-    And I should see "Collections: this is a test!, Collection#entries, Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, Initialize, Ellipsis Path, YAML with Dots" in "_site/index.html" if on Windows
+    And I should see "Collections: this is a test!, Collection#entries, Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, Initialize, Ellipsis Path, Site#generate, YAML with Dots" in "_site/index.html" if platform supports symlinks
+    And I should see "Collections: this is a test!, Collection#entries, Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, Initialize, Ellipsis Path, YAML with Dots" in "_site/index.html" if platform does not support symlinks
 
   Scenario: Sort all entries by a Front Matter key defined in all entries
     Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}"
diff --git a/features/step_definitions.rb b/features/step_definitions.rb
index 616ab0b6656..b8c0e35b42a 100644
--- a/features/step_definitions.rb
+++ b/features/step_definitions.rb
@@ -287,28 +287,28 @@
 
 #
 
-Then(%r!^I should (not )?see "(.*)" in "(.*)" if on Windows$!) do |negative, text, file|
+Then(%r!^I should (not )?see "(.*)" in "(.*)" if platform does not support symlinks$!) do |negative, text, file|
   step %(the "#{file}" file should exist)
   regexp = Regexp.new(text, Regexp::MULTILINE)
   if negative.nil? || negative.empty?
-    if Jekyll::Utils::Platforms.really_windows?
-      expect(file_contents(file)).to match regexp
-    else
+    if Platform.supports_symlink?
       expect(file_contents(file)).not_to match regexp
+    else
+      expect(file_contents(file)).to match regexp
     end
   end
 end
 
 #
 
-Then(%r!^I should (not )?see "(.*)" in "(.*)" unless Windows$!) do |negative, text, file|
+Then(%r!^I should (not )?see "(.*)" in "(.*)" if platform supports symlinks$!) do |negative, text, file|
   step %(the "#{file}" file should exist)
   regexp = Regexp.new(text, Regexp::MULTILINE)
   if negative.nil? || negative.empty?
-    if Jekyll::Utils::Platforms.really_windows?
-      expect(file_contents(file)).not_to match regexp
-    else
+    if Platform.supports_symlink?
       expect(file_contents(file)).to match regexp
+    else
+      expect(file_contents(file)).not_to match regexp
     end
   end
 end
diff --git a/features/support/helpers.rb b/features/support/helpers.rb
index b6e77eec4b4..66e690afe02 100644
--- a/features/support/helpers.rb
+++ b/features/support/helpers.rb
@@ -18,6 +18,13 @@ def self.jekyll_bin; source_dir.join("exe", "jekyll"); end
   def self.source_dir; SOURCE_DIR; end
 end
 
+class Platform
+  REF_FILE = File.expand_path("../../test/source/symlink-test/symlinked-file", __dir__)
+
+  def self.supports_symlink?; File.symlink?(REF_FILE); end
+end
+
+
 #
 
 def file_content_from_hash(input_hash)