From a0a49546f3d3ac1e9095910db3b0538df79b9111 Mon Sep 17 00:00:00 2001 From: Matthew Lieder Date: Thu, 26 Oct 2023 14:05:21 -0500 Subject: [PATCH 1/6] #1144@patch: Run tests against newer Node.js versions Also fixed tests that were failing locally for me (running on Node.js 18), for various reasons. --- .github/workflows/pull_request.yml | 2 +- .../html-input-element/HTMLInputElementDateUtility.ts | 6 +++--- .../nodes/html-input-element/HTMLInputElement.test.ts | 1 + packages/happy-dom/test/window/Window.test.ts | 4 ++-- .../test/UncaughtExceptionObserver.test.ts | 10 ++++++---- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index db4974631..841bf8bab 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16] + node-version: [16, 18, 20] steps: - uses: actions/checkout@v3 diff --git a/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts b/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts index f89e14658..0187c1a4a 100644 --- a/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts +++ b/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts @@ -14,8 +14,8 @@ export default class HTMLInputElementDateUtility { date.setUTCDate(date.getUTCDate() - day + 3); const firstThursday = date.getTime(); date.setUTCMonth(0, 1); - if (date.getDay() !== 4) { - date.setUTCMonth(0, 1 + ((4 - date.getDay() + 7) % 7)); + if (date.getUTCDay() !== 4) { + date.setUTCMonth(0, 1 + ((4 - date.getUTCDay() + 7) % 7)); } return ( date.getUTCFullYear() + @@ -37,7 +37,7 @@ export default class HTMLInputElementDateUtility { } const date = new Date(`${Y}-01-01T00:00Z`); const jan4th = new Date(`${Y}-01-04T00:00Z`); - const jan4thDay = (jan4th.getDay() + 6) % 7; + const jan4thDay = (jan4th.getUTCDay() + 6) % 7; const ordinalDate = 1 + (Number(W) - 1) * 7 - jan4thDay + 3; date.setUTCDate(ordinalDate); if (date.getUTCFullYear() > Number(Y)) { diff --git a/packages/happy-dom/test/nodes/html-input-element/HTMLInputElement.test.ts b/packages/happy-dom/test/nodes/html-input-element/HTMLInputElement.test.ts index abceaa4c8..1c181aa39 100644 --- a/packages/happy-dom/test/nodes/html-input-element/HTMLInputElement.test.ts +++ b/packages/happy-dom/test/nodes/html-input-element/HTMLInputElement.test.ts @@ -390,6 +390,7 @@ describe('HTMLInputElement', () => { { type: 'time', value: '00:00', want: new Date('1970-01-01T00:00Z') }, { type: 'time', value: '12:00', want: new Date('1970-01-01T12:00Z') }, { type: 'time', value: '18:55', want: new Date('1970-01-01T18:55Z') }, + { type: 'week', value: '1981-W01', want: new Date('1980-12-29T00:00Z') }, { type: 'week', value: '2023-W22', want: new Date('2023-05-29T00:00Z') } ])(`Should return valid date for type $type with valid value`, ({ type, value, want }) => { element.type = type; diff --git a/packages/happy-dom/test/window/Window.test.ts b/packages/happy-dom/test/window/Window.test.ts index 39a4363af..41d2761e3 100644 --- a/packages/happy-dom/test/window/Window.test.ts +++ b/packages/happy-dom/test/window/Window.test.ts @@ -874,7 +874,7 @@ describe('Window', () => { expect(((errorEvent)).error?.message).toBe('Test error'); expect(((errorEvent)).message).toBe('Test error'); resolve(null); - }, 15); + }, 20); }); }); }); @@ -1030,7 +1030,7 @@ describe('Window', () => { expect(((errorEvent)).error?.message).toBe('Test error'); expect(((errorEvent)).message).toBe('Test error'); resolve(null); - }, 10); + }, 20); }); }); }); diff --git a/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts b/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts index a3b42305f..7d5f9df22 100644 --- a/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts +++ b/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts @@ -70,15 +70,17 @@ async function itObservesUnhandledJavaScriptFetchRejections(): Promise { } if ( - errorEvent.error.message !== - 'Fetch to "https://localhost:3000/404.js" failed. Error: connect ECONNREFUSED 127.0.0.1:3000' + !errorEvent.error.message.startsWith( + 'Fetch to "https://localhost:3000/404.js" failed. Error: connect ECONNREFUSED' + ) ) { throw new Error('Error message not correct.'); } if ( - errorEvent.message !== - 'Fetch to "https://localhost:3000/404.js" failed. Error: connect ECONNREFUSED 127.0.0.1:3000' + !errorEvent.message.startsWith( + 'Fetch to "https://localhost:3000/404.js" failed. Error: connect ECONNREFUSED' + ) ) { throw new Error('Error message not correct.'); } From 676e3138182167b2c86b4d1ccb73ab00d4272dd0 Mon Sep 17 00:00:00 2001 From: Matthew Lieder Date: Thu, 26 Oct 2023 14:12:36 -0500 Subject: [PATCH 2/6] #1144@patch: Add continue-on-error. --- .github/workflows/pull_request.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 841bf8bab..fe5aba889 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -3,6 +3,7 @@ on: pull_request jobs: build: runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: node-version: [16, 18, 20] From a35f7b274562bbdaf170e11f4c4b83e5d7c173fa Mon Sep 17 00:00:00 2001 From: Matthew Lieder Date: Thu, 26 Oct 2023 14:36:31 -0500 Subject: [PATCH 3/6] #1144@patch: Fix flaky test. --- .../test/UncaughtExceptionObserver.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts b/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts index 7d5f9df22..ad55315b9 100644 --- a/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts +++ b/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts @@ -61,7 +61,12 @@ async function itObservesUnhandledJavaScriptFetchRejections(): Promise { `); - await new Promise((resolve) => setTimeout(resolve, 10)); + for (let i = 0; i < 10; i++) { + await new Promise((resolve) => setTimeout(resolve, 10)); + if (errorEvent) { + break; + } + } observer.disconnect(); From f26b0843b6ab180af7e2dbb452ddd85f093063d6 Mon Sep 17 00:00:00 2001 From: Matthew Lieder Date: Thu, 26 Oct 2023 15:56:59 -0500 Subject: [PATCH 4/6] #1144@patch: Fix test on Node 20. --- .../test/UncaughtExceptionObserver.test.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts b/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts index ad55315b9..8d5feaf2f 100644 --- a/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts +++ b/packages/uncaught-exception-observer/test/UncaughtExceptionObserver.test.ts @@ -74,19 +74,11 @@ async function itObservesUnhandledJavaScriptFetchRejections(): Promise { throw new Error('Error event not dispatched.'); } - if ( - !errorEvent.error.message.startsWith( - 'Fetch to "https://localhost:3000/404.js" failed. Error: connect ECONNREFUSED' - ) - ) { + if (!errorEvent.error.message.startsWith('Fetch to "https://localhost:3000/404.js" failed.')) { throw new Error('Error message not correct.'); } - if ( - !errorEvent.message.startsWith( - 'Fetch to "https://localhost:3000/404.js" failed. Error: connect ECONNREFUSED' - ) - ) { + if (!errorEvent.message.startsWith('Fetch to "https://localhost:3000/404.js" failed.')) { throw new Error('Error message not correct.'); } } From 49d489d01473e217bc5040a0824d47d70224d240 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Fri, 27 Oct 2023 23:29:51 +0200 Subject: [PATCH 5/6] #1144@trivial: Updates Date ISO week function to a more battle tested. --- .../HTMLInputElementDateUtility.ts | 28 +++++++++++-------- ...ts => HTMLInputElementDateUtility.test.ts} | 4 +-- 2 files changed, 18 insertions(+), 14 deletions(-) rename packages/happy-dom/test/nodes/html-input-element/{HTMLInputDateUtility.test.ts => HTMLInputElementDateUtility.test.ts} (98%) diff --git a/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts b/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts index 0187c1a4a..7ae7c33bd 100644 --- a/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts +++ b/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts @@ -5,24 +5,28 @@ export default class HTMLInputElementDateUtility { /** * Returns iso week number from given date * + * @see https://stackoverflow.com/a/6117889 * @param date Date or number. * @returns Iso-week string. */ public static dateIsoWeek(date: Date | number): string { - date = new Date(date); - const day = (date.getUTCDay() + 6) % 7; - date.setUTCDate(date.getUTCDate() - day + 3); - const firstThursday = date.getTime(); - date.setUTCMonth(0, 1); - if (date.getUTCDay() !== 4) { - date.setUTCMonth(0, 1 + ((4 - date.getUTCDay() + 7) % 7)); - } - return ( - date.getUTCFullYear() + - '-W' + - String(1 + Math.ceil((firstThursday - date.getTime()) / 604800000)).padStart(2, '0') + const parsedDate = typeof date === 'number' ? new Date(date) : date; + // Copy date so don't modify original + const newDate = new Date( + Date.UTC(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()) + ); + // Set to nearest Thursday: current date + 4 - current day number + // Make Sunday's day number 7 + newDate.setUTCDate(newDate.getUTCDate() + 4 - (newDate.getUTCDay() || 7)); + // Get first day of year + const yearStart = new Date(Date.UTC(newDate.getUTCFullYear(), 0, 1)); + // Calculate full weeks to nearest Thursday + const weekNo = Math.ceil( + (((newDate) - (yearStart)) / 86400000 + 1) / 7 ); + return `${newDate.getUTCFullYear()}-W${weekNo < 10 ? '0' : ''}${weekNo}`; } + /** * Returns a date object for monday of given iso week string (\d\d\d\d-W\d\d) * diff --git a/packages/happy-dom/test/nodes/html-input-element/HTMLInputDateUtility.test.ts b/packages/happy-dom/test/nodes/html-input-element/HTMLInputElementDateUtility.test.ts similarity index 98% rename from packages/happy-dom/test/nodes/html-input-element/HTMLInputDateUtility.test.ts rename to packages/happy-dom/test/nodes/html-input-element/HTMLInputElementDateUtility.test.ts index e2b4bcb34..72777fdc0 100644 --- a/packages/happy-dom/test/nodes/html-input-element/HTMLInputDateUtility.test.ts +++ b/packages/happy-dom/test/nodes/html-input-element/HTMLInputElementDateUtility.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'; import HTMLInputElementDateUtility from '../../../src/nodes/html-input-element/HTMLInputElementDateUtility.js'; describe('HTMLInputElementDateUtility', () => { - describe('dateToIsoWeek()', () => { + describe('dateIsoWeek()', () => { it('Returns the ISO week number', () => { expect(HTMLInputElementDateUtility.dateIsoWeek(new Date('2021-01-01'))).toBe('2020-W53'); expect(HTMLInputElementDateUtility.dateIsoWeek(new Date('2021-01-03'))).toBe('2020-W53'); @@ -35,7 +35,7 @@ describe('HTMLInputElementDateUtility', () => { }); }); - describe('IsoWeekToDate()', () => { + describe('isoWeekDate()', () => { it('Returns the ISO week number', () => { expect(HTMLInputElementDateUtility.isoWeekDate('2020-W53')).toEqual( new Date('2020-12-28T00:00Z') From a56ed6a42eb92a34e25140ed97e3026c539d35fd Mon Sep 17 00:00:00 2001 From: David Ortner Date: Fri, 27 Oct 2023 23:32:34 +0200 Subject: [PATCH 6/6] #1144@trivial: Updates Date ISO week function to a more battle tested. --- .../HTMLInputElementDateUtility.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts b/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts index 7ae7c33bd..4d0446de4 100644 --- a/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts +++ b/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts @@ -10,21 +10,19 @@ export default class HTMLInputElementDateUtility { * @returns Iso-week string. */ public static dateIsoWeek(date: Date | number): string { - const parsedDate = typeof date === 'number' ? new Date(date) : date; + date = typeof date === 'number' ? new Date(date) : date; // Copy date so don't modify original - const newDate = new Date( - Date.UTC(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()) - ); + date = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); // Set to nearest Thursday: current date + 4 - current day number // Make Sunday's day number 7 - newDate.setUTCDate(newDate.getUTCDate() + 4 - (newDate.getUTCDay() || 7)); + date.setUTCDate(date.getUTCDate() + 4 - (date.getUTCDay() || 7)); // Get first day of year - const yearStart = new Date(Date.UTC(newDate.getUTCFullYear(), 0, 1)); + const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1)); // Calculate full weeks to nearest Thursday const weekNo = Math.ceil( - (((newDate) - (yearStart)) / 86400000 + 1) / 7 + (((date) - (yearStart)) / 86400000 + 1) / 7 ); - return `${newDate.getUTCFullYear()}-W${weekNo < 10 ? '0' : ''}${weekNo}`; + return `${date.getUTCFullYear()}-W${weekNo < 10 ? '0' : ''}${weekNo}`; } /**