diff --git a/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/project-tools-more-dropdown-button.tsx b/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/project-tools-more-dropdown-button.tsx index 0d7ba75283..656637b290 100644 --- a/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/project-tools-more-dropdown-button.tsx +++ b/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/project-tools-more-dropdown-button.tsx @@ -17,12 +17,8 @@ function ProjectToolsMoreDropdownButton() { {t('more')} -
  • - -
  • -
  • - -
  • + +
    ) diff --git a/services/web/scripts/recurly/collect_paypal_past_due_invoice.mjs b/services/web/scripts/recurly/collect_paypal_past_due_invoice.mjs index 2bf827bae8..7f058b800b 100644 --- a/services/web/scripts/recurly/collect_paypal_past_due_invoice.mjs +++ b/services/web/scripts/recurly/collect_paypal_past_due_invoice.mjs @@ -25,7 +25,7 @@ const handleAPIError = async (source, id, error) => { * USERS_COLLECTED: string[], * }>} */ -const main = async () => { +export async function collectPastDueInvoices(DRY_RUN = false) { const attemptInvoiceCollection = async invoice => { const isPaypal = await isAccountUsingPaypal(invoice) @@ -84,8 +84,6 @@ const main = async () => { } } - const argv = minimist(process.argv.slice(2)) - const DRY_RUN = argv.n !== undefined const INVOICES_COLLECTED = [] const INVOICES_COLLECTED_SUCCESS = [] const USERS_COLLECTED = [] @@ -105,19 +103,22 @@ const main = async () => { } } finally { logger.info( - `DONE (DRY_RUN=${DRY_RUN}). ${INVOICES_COLLECTED.length} invoices collection attempts for ${USERS_COLLECTED.length} users. ${INVOICES_COLLECTED_SUCCESS.length} successful collections` - ) - console.dir( { INVOICES_COLLECTED, INVOICES_COLLECTED_SUCCESS, USERS_COLLECTED, }, - { maxArrayLength: null } + `DONE (DRY_RUN=${DRY_RUN}). ${INVOICES_COLLECTED.length} invoices collection attempts for ${USERS_COLLECTED.length} users. ${INVOICES_COLLECTED_SUCCESS.length} successful collections` ) } } +async function main() { + const argv = minimist(process.argv.slice(2)) + const DRY_RUN = argv.n !== undefined + await collectPastDueInvoices(DRY_RUN) +} + if (fileURLToPath(import.meta.url) === process.argv[1]) { try { await scriptRunner(main) @@ -128,5 +129,3 @@ if (fileURLToPath(import.meta.url) === process.argv[1]) { process.exit(1) } } - -export default { main } diff --git a/services/web/test/acceptance/src/CollectPayPalPastDueInvoiceTest.mjs b/services/web/test/acceptance/src/CollectPayPalPastDueInvoiceTest.mjs index db75aa6a47..6e44f0e041 100644 --- a/services/web/test/acceptance/src/CollectPayPalPastDueInvoiceTest.mjs +++ b/services/web/test/acceptance/src/CollectPayPalPastDueInvoiceTest.mjs @@ -2,12 +2,10 @@ import sinon from 'sinon' import chai, { expect } from 'chai' import chaiAsPromised from 'chai-as-promised' import sinonChai from 'sinon-chai' -import CollectPaypalPastDueInvoice from '../../../scripts/recurly/collect_paypal_past_due_invoice.mjs' +import { collectPastDueInvoices } from '../../../scripts/recurly/collect_paypal_past_due_invoice.mjs' import RecurlyWrapper from '../../../app/src/Features/Subscription/RecurlyWrapper.js' import OError from '@overleaf/o-error' -const { main } = CollectPaypalPastDueInvoice - chai.use(chaiAsPromised) chai.use(sinonChai) @@ -213,7 +211,7 @@ describe('CollectPayPalPastDueInvoice', function () { it('collects one valid invoice', async function () { fakeApiRequests([200]) - const r = await main() + const r = await collectPastDueInvoices() expect(r).to.eql({ INVOICES_COLLECTED: [200], INVOICES_COLLECTED_SUCCESS: [200], @@ -224,7 +222,7 @@ describe('CollectPayPalPastDueInvoice', function () { it('collects several pages', async function () { // 10 invoices, from 200 to 209 fakeApiRequests([...Array(10).keys()].map(i => i + 200)) - const r = await main() + const r = await collectPastDueInvoices() expect(r).to.eql({ INVOICES_COLLECTED: [200, 201, 202, 203, 204, 205, 206, 207, 208, 209], @@ -253,7 +251,7 @@ describe('CollectPayPalPastDueInvoice', function () { it("resolves when no invoices are processed so we don't fail in staging", async function () { fakeApiRequests([404]) - const r = await main() + const r = await collectPastDueInvoices() expect(r).to.eql({ INVOICES_COLLECTED: [404], INVOICES_COLLECTED_SUCCESS: [], @@ -263,7 +261,7 @@ describe('CollectPayPalPastDueInvoice', function () { it('doesnt reject when there are no invoices', async function () { fakeApiRequests([]) - const r = await main() + const r = await collectPastDueInvoices() expect(r).to.eql({ INVOICES_COLLECTED: [], INVOICES_COLLECTED_SUCCESS: [], @@ -273,7 +271,7 @@ describe('CollectPayPalPastDueInvoice', function () { it("resolves when collection is partially successful so we don't fail in prod", async function () { fakeApiRequests([200, 404]) - const r = await main() + const r = await collectPastDueInvoices() expect(r).to.eql({ INVOICES_COLLECTED: [200, 404], INVOICES_COLLECTED_SUCCESS: [200], diff --git a/services/web/test/frontend/cut-log-noise.ts b/services/web/test/frontend/cut-log-noise.ts index feba2e2383..61432d388d 100644 --- a/services/web/test/frontend/cut-log-noise.ts +++ b/services/web/test/frontend/cut-log-noise.ts @@ -8,3 +8,8 @@ if (process.env.VERBOSE_LOGGING === 'true') { debugConsole.warn = () => {} debugConsole.error = () => {} } + +before(function () { + // Range.getClientRects doesn't exist yet in jsdom + window.Range.prototype.getClientRects = () => [] as any as DOMRectList +}) diff --git a/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx b/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx index 00a8593169..4ad1bc7443 100644 --- a/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx +++ b/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx @@ -340,8 +340,6 @@ describe('', function () { '/learn/how-to/Overleaf_premium_features' ) - fireEvent.click(links[0]) - window.metaAttributesCache.delete('ol-usersBestSubscription') }) } diff --git a/services/web/test/frontend/features/source-editor/extensions/scroll-position.test.ts b/services/web/test/frontend/features/source-editor/extensions/scroll-position.test.ts index d5b9b68781..953982c0ed 100644 --- a/services/web/test/frontend/features/source-editor/extensions/scroll-position.test.ts +++ b/services/web/test/frontend/features/source-editor/extensions/scroll-position.test.ts @@ -37,15 +37,10 @@ describe('CodeMirror scroll position extension', function () { sinon .stub(HTMLElement.prototype, 'getBoundingClientRect') .returns({ top: 100, left: 0, right: 500, bottom: 200 } as DOMRect) - - // Range.getClientRects doesn't exist yet in jsdom - window.Range.prototype.getClientRects = sinon.stub().returns([]) }) afterEach(function () { sinon.restore() - // @ts-ignore - delete window.Range.prototype.getClientRects }) it('stores scroll position when the view is destroyed', async function () {