-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(sites-29590): support user bearer token #22
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,7 @@ function buildFileSystemUploadOptions(target, token) { | |
* | ||
* @returns {FileSystemUpload} The file uploader | ||
*/ | ||
/* c8 ignore start */ | ||
function createFileUploader() { | ||
const fileUpload = new FileSystemUpload(); | ||
|
||
|
@@ -79,9 +80,18 @@ function createFileUploader() { | |
|
||
return fileUpload; | ||
} | ||
/* c8 ignore end */ | ||
|
||
export async function uploadAssets(target, token, assetFolder) { | ||
const fileUpload = createFileUploader(); | ||
/** | ||
* Upload assets to AEM. | ||
* @param {string} target - The URL of the AEM Assets instance | ||
* @param {string} token - The bearer token for authentication | ||
* @param {string} assetFolder - The path to the asset folder to upload the assets from | ||
* @param fileUploader - The file uploader to use for uploading assets (optional) | ||
* @return {Promise<UploadResult>} - The result of the upload operation as JSON. | ||
*/ | ||
export async function uploadAssets(target, token, assetFolder, fileUploader = null) { | ||
const fileUpload = fileUploader || createFileUploader(); | ||
Comment on lines
+93
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One doubt: why are we allowing a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passing the fileUploader allows me to test the fact that it was uploaded. This is a super weird/hard function to test. Do you see any other way of testing this? |
||
const options = buildFileSystemUploadOptions(target, token); | ||
return await fileUpload.upload(options, [assetFolder]); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright 2025 Adobe. All rights reserved. | ||
* This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. You may obtain a copy | ||
* of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under | ||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
* OF ANY KIND, either express or implied. See the License for the specific language | ||
* governing permissions and limitations under the License. | ||
*/ | ||
import { expect } from 'chai'; | ||
import { getDamRootFolder } from '../../src/aem/aem-util.js'; | ||
|
||
describe('aem-utils', function () { | ||
/** | ||
* Test getDamRootFolder function to return the correct root folder that's found | ||
* in the asset mapping object. | ||
*/ | ||
it('test getDamRootFolder', async () => { | ||
let assetMapping = new Map([ | ||
['http://www.example.com/image.png', '/content/dam/xwalk/image.png'], | ||
]); | ||
expect(getDamRootFolder(assetMapping)).to.equal('xwalk'); | ||
|
||
assetMapping.clear(); | ||
|
||
assetMapping.set('http://www.example.com/image.png', '/content/dam/image.png'); | ||
expect(() => getDamRootFolder(assetMapping)).to.throw(Error, 'Unable to locate the DAM root folder'); | ||
|
||
assetMapping.clear(); | ||
assetMapping.set('http://www.example.com/image.png', '/content/dam/image.png'); | ||
assetMapping.set('http://www.example.com/image2.png', '/content/dam/first/image.png'); | ||
expect(getDamRootFolder(assetMapping)).to.equal('first'); | ||
|
||
assetMapping.clear(); | ||
assetMapping.set('http://www.example.com/image.png', '/image.png'); | ||
assetMapping.set('http://www.example.com/image2.png', '/content/dam/first/image.png'); | ||
assetMapping.set('http://www.example.com/image3.png', '/content/dam/second/image.png'); | ||
expect(getDamRootFolder(assetMapping)).to.equal('first'); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright 2025 Adobe. All rights reserved. | ||
* This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. You may obtain a copy | ||
* of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under | ||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
* OF ANY KIND, either express or implied. See the License for the specific language | ||
* governing permissions and limitations under the License. | ||
*/ | ||
import { expect } from 'chai'; | ||
import { cleanup, downloadAssets } from '../../src/aem/download-assets.js'; | ||
import nock from 'nock'; | ||
import path from 'path'; | ||
import { fileURLToPath } from 'url'; | ||
import fs from 'fs'; | ||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
|
||
describe('download assets', function () { | ||
|
||
let downloadFolder; | ||
|
||
beforeEach(() => { | ||
downloadFolder = path.join(__dirname, 'assets'); | ||
}); | ||
|
||
afterEach(() => { | ||
cleanup(downloadFolder); | ||
}); | ||
|
||
it('expect download to be successful', async () => { | ||
const scope = nock('http://www.aem.com') | ||
.get('/asset1.jpg') | ||
.replyWithFile(200, path.resolve(__dirname, 'fixtures/image1.jpeg')); | ||
Comment on lines
+33
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is awesome! Makes mocking api calls so much cleaner. clap-clap |
||
|
||
const mapping = new Map([ | ||
['http://www.aem.com/asset1.jpg', '/content/dam/xwalk/image1.jpg'], | ||
]); | ||
|
||
await downloadAssets(mapping, downloadFolder); | ||
expect(fs.existsSync(path.join(downloadFolder, 'xwalk/image1.jpg'))).to.be.true; | ||
|
||
await scope.done(); | ||
}); | ||
|
||
it('expect download to be successful after retry', async () => { | ||
const scope = nock('http://www.aem.com') | ||
.get('/asset1.jpg') | ||
.replyWithError('Server error') | ||
.get('/asset1.jpg') | ||
.replyWithFile(200, path.resolve(__dirname, 'fixtures/image1.jpeg')); | ||
|
||
const mapping = new Map([ | ||
['http://www.aem.com/asset1.jpg', '/content/dam/xwalk/image1.jpg'], | ||
]); | ||
|
||
await downloadAssets(mapping, downloadFolder, 3, 0); | ||
expect(fs.existsSync(path.join(downloadFolder, 'xwalk/image1.jpg'))).to.be.true; | ||
|
||
await scope.done(); | ||
}); | ||
|
||
// write a test that expect to exhaust retires and throw error | ||
it('expect download to fail after max retries', async () => { | ||
const scope = nock('http://www.aem.com') | ||
.get('/asset1.jpg') | ||
.replyWithError('Server error') | ||
.get('/asset2.jpg') | ||
.replyWithError('Server error') | ||
.get('/asset3.jpg') | ||
.replyWithFile(200, path.resolve(__dirname, 'fixtures/image3.jpeg')); | ||
|
||
const mapping = new Map([ | ||
['http://www.aem.com/asset1.jpg', '/content/dam/xwalk/image1.jpg'], | ||
['http://www.aem.com/asset2.jpg', '/content/dam/xwalk/image2.jpg'], | ||
['http://www.aem.com/asset3.jpg', '/content/dam/xwalk/image3.jpg'], | ||
]); | ||
|
||
const results = await downloadAssets(mapping, downloadFolder, 1, 0); | ||
expect(results.filter((result) => result.status === 'rejected').length).to.equal(2); | ||
expect(results.filter((result) => result.status === 'fulfilled').length).to.equal(1); | ||
|
||
await scope.done(); | ||
}); | ||
|
||
it('expect download to fail with bad response', async () => { | ||
const scope = nock('http://www.aem.com') | ||
.get('/asset1.jpg') | ||
.reply(404); | ||
|
||
const mapping = new Map([ | ||
['http://www.aem.com/asset1.jpg', '/content/dam/xwalk/image1.jpg'], | ||
]); | ||
|
||
try { | ||
await downloadAssets(mapping, downloadFolder, 1, 0); | ||
} catch (error) { | ||
expect(error.message).to.equal('Failed to fetch http://www.aem.com/asset1.jpg. Status: 404.'); | ||
} | ||
|
||
await scope.done(); | ||
}); | ||
|
||
}); |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Copyright 2025 Adobe. All rights reserved. | ||
* This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. You may obtain a copy | ||
* of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under | ||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
* OF ANY KIND, either express or implied. See the License for the specific language | ||
* governing permissions and limitations under the License. | ||
*/ | ||
import { expect } from 'chai'; | ||
import { uploadAssets } from '../../src/aem/upload-assets.js'; | ||
import { FileSystemUpload } from '@adobe/aem-upload'; | ||
import sinon from 'sinon'; | ||
|
||
describe('upload assets', function () { | ||
|
||
afterEach(() => { | ||
sinon.restore(); | ||
}); | ||
|
||
it('validate the upload call has the correct arguments', async function () { | ||
const fsUpload = new FileSystemUpload(); | ||
const uploadStub = sinon.stub(fsUpload, 'upload').resolves('success'); | ||
|
||
await uploadAssets('http://www.aem.com', 'abcd123', '/assets', fsUpload); | ||
expect(uploadStub.calledOnce).to.be.true; | ||
|
||
// expect the upload to have been called with the correct options | ||
const optionArgs = uploadStub.getCall(0).args[0]; | ||
expect(optionArgs.options.url).to.equal('http://www.aem.com/content/dam'); | ||
|
||
const pathArgs = uploadStub.getCall(0).args[1]; | ||
expect(pathArgs[0]).to.equal('/assets'); | ||
}); | ||
|
||
it('validate the upload call has the correct arguments for https', async function () { | ||
const fsUpload = new FileSystemUpload(); | ||
const uploadStub = sinon.stub(fsUpload, 'upload').resolves('success'); | ||
|
||
await uploadAssets('https://www.aem.com', 'abcd123', '/assets', fsUpload); | ||
expect(uploadStub.calledOnce).to.be.true; | ||
|
||
// expect the upload to have been called with the correct options | ||
const optionArgs = uploadStub.getCall(0).args[0]; | ||
expect(optionArgs.options.url).to.equal('https://www.aem.com/content/dam'); | ||
|
||
const pathArgs = uploadStub.getCall(0).args[1]; | ||
expect(pathArgs[0]).to.equal('/assets'); | ||
}); | ||
|
||
it('validate the upload call has the correct arguments for non http(s) urls', async function () { | ||
const fsUpload = new FileSystemUpload(); | ||
const uploadStub = sinon.stub(fsUpload, 'upload').resolves('success'); | ||
|
||
await uploadAssets('www.aem.com', 'abcd123', '/assets', fsUpload); | ||
expect(uploadStub.calledOnce).to.be.true; | ||
|
||
// expect the upload to have been called with the correct options | ||
const optionArgs = uploadStub.getCall(0).args[0]; | ||
expect(optionArgs.options.url).to.equal('https://www.aem.com/content/dam'); | ||
|
||
const pathArgs = uploadStub.getCall(0).args[1]; | ||
expect(pathArgs[0]).to.equal('/assets'); | ||
}); | ||
}); |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maxRetries
also be read from theprocess.env.MAX_RETRIES
(similar to how it is done in package-helper.js)?retryDelay
should be just declare a const and not have it as an input (to keep the method signatures consistent)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, I think no one is going to mess with those environment variables. If it doesn't work after a specific number of tries, there's something wrong.