2021-07-21 16:28:39 +03:00
|
|
|
// Switch these lines once there are useful utils
|
|
|
|
// const testUtils = require('./utils');
|
|
|
|
require('./utils');
|
|
|
|
|
2022-10-13 10:16:09 +03:00
|
|
|
const assert = require('assert');
|
2021-07-21 18:25:41 +03:00
|
|
|
const fs = require('fs-extra');
|
2021-07-21 16:28:39 +03:00
|
|
|
const path = require('path');
|
|
|
|
const sinon = require('sinon');
|
|
|
|
const MembersCSVImporter = require('..');
|
|
|
|
|
|
|
|
const csvPath = path.join(__dirname, '/fixtures/');
|
|
|
|
|
|
|
|
describe('Importer', function () {
|
2021-07-21 18:25:41 +03:00
|
|
|
let fsWriteSpy;
|
2022-10-13 09:21:08 +03:00
|
|
|
let memberCreateStub;
|
|
|
|
let knexStub;
|
|
|
|
let sendEmailStub;
|
2022-10-13 11:16:37 +03:00
|
|
|
let membersApiStub;
|
2021-07-21 18:25:41 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
const defaultAllowedFields = {
|
|
|
|
email: 'email',
|
|
|
|
name: 'name',
|
|
|
|
note: 'note',
|
|
|
|
subscribed_to_emails: 'subscribed',
|
|
|
|
created_at: 'created_at',
|
|
|
|
complimentary_plan: 'complimentary_plan',
|
|
|
|
stripe_customer_id: 'stripe_customer_id',
|
2022-10-24 13:03:44 +03:00
|
|
|
labels: 'labels'
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
};
|
|
|
|
|
2021-07-21 18:25:41 +03:00
|
|
|
beforeEach(function () {
|
|
|
|
fsWriteSpy = sinon.spy(fs, 'writeFile');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
2022-08-23 22:19:30 +03:00
|
|
|
const writtenFile = fsWriteSpy.args?.[0]?.[0];
|
2021-07-21 18:25:41 +03:00
|
|
|
|
|
|
|
if (writtenFile) {
|
|
|
|
fs.removeSync(writtenFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
2022-10-13 09:21:08 +03:00
|
|
|
// @NOTE: this is way too much mocking! the MembersCSVImporter constructor API should be simplified
|
|
|
|
const buildMockImporterInstance = () => {
|
|
|
|
const defaultProduct = {
|
|
|
|
id: 'default_product_id'
|
|
|
|
};
|
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
memberCreateStub = sinon.stub().resolves({
|
|
|
|
id: `test_member_id`
|
|
|
|
});
|
2022-10-13 11:16:37 +03:00
|
|
|
membersApiStub = {
|
2022-10-13 09:21:08 +03:00
|
|
|
productRepository: {
|
2022-10-20 10:02:27 +03:00
|
|
|
getDefaultProduct: async () => {
|
|
|
|
return defaultProduct;
|
2021-07-21 16:28:39 +03:00
|
|
|
}
|
2022-10-13 09:21:08 +03:00
|
|
|
},
|
|
|
|
members: {
|
|
|
|
get: async () => {
|
|
|
|
return null;
|
|
|
|
},
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
create: memberCreateStub,
|
|
|
|
update: sinon.stub().resolves(null),
|
|
|
|
linkStripeCustomer: sinon.stub().resolves(null)
|
2022-10-13 09:21:08 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
knexStub = {
|
|
|
|
transaction: sinon.stub().resolves({
|
|
|
|
rollback: () => {},
|
|
|
|
commit: () => {}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
sendEmailStub = sinon.stub();
|
|
|
|
|
|
|
|
return new MembersCSVImporter({
|
|
|
|
storagePath: csvPath,
|
|
|
|
getTimezone: sinon.stub().returns('UTC'),
|
2022-10-13 11:16:37 +03:00
|
|
|
getMembersApi: () => membersApiStub,
|
2022-10-13 09:21:08 +03:00
|
|
|
sendEmail: sendEmailStub,
|
|
|
|
isSet: sinon.stub(),
|
|
|
|
addJob: sinon.stub(),
|
|
|
|
knex: knexStub,
|
|
|
|
urlFor: sinon.stub(),
|
|
|
|
context: {importer: true}
|
|
|
|
});
|
|
|
|
};
|
2021-07-21 16:28:39 +03:00
|
|
|
|
2022-10-13 09:21:08 +03:00
|
|
|
describe('process', function () {
|
|
|
|
it('should import a CSV file', async function () {
|
2021-07-21 16:28:39 +03:00
|
|
|
const LabelModelStub = {
|
|
|
|
findOne: sinon.stub().resolves(null)
|
|
|
|
};
|
|
|
|
|
2022-10-13 09:21:08 +03:00
|
|
|
const importer = buildMockImporterInstance();
|
2021-07-23 19:29:19 +03:00
|
|
|
|
|
|
|
const result = await importer.process({
|
|
|
|
pathToCSV: `${csvPath}/single-column-with-header.csv`,
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
headerMapping: defaultAllowedFields,
|
2021-07-23 19:29:19 +03:00
|
|
|
importLabel: {
|
|
|
|
name: 'test import'
|
|
|
|
},
|
|
|
|
user: {
|
|
|
|
email: 'test@example.com'
|
|
|
|
},
|
|
|
|
LabelModel: LabelModelStub
|
|
|
|
});
|
|
|
|
|
|
|
|
should.exist(result.meta);
|
|
|
|
should.exist(result.meta.stats);
|
|
|
|
should.exist(result.meta.stats.imported);
|
|
|
|
result.meta.stats.imported.should.equal(2);
|
|
|
|
|
|
|
|
should.exist(result.meta.stats.invalid);
|
|
|
|
should.equal(result.meta.import_label, null);
|
|
|
|
|
2021-07-28 18:13:48 +03:00
|
|
|
should.exist(result.meta.originalImportSize);
|
|
|
|
result.meta.originalImportSize.should.equal(2);
|
|
|
|
|
2021-07-21 18:25:41 +03:00
|
|
|
fsWriteSpy.calledOnce.should.be.true();
|
2022-04-13 19:35:24 +03:00
|
|
|
|
|
|
|
// Called at least once
|
|
|
|
memberCreateStub.notCalled.should.be.false();
|
|
|
|
memberCreateStub.firstCall.lastArg.context.import.should.be.true();
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
|
|
|
|
it('should import a CSV in the default Members export format', async function () {
|
|
|
|
const internalLabel = {
|
|
|
|
name: 'Test Import'
|
|
|
|
};
|
|
|
|
const LabelModelStub = {
|
|
|
|
findOne: sinon.stub()
|
|
|
|
.withArgs({
|
|
|
|
name: 'Test Import'
|
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
name: 'Test Import'
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
const importer = buildMockImporterInstance();
|
|
|
|
const result = await importer.process({
|
|
|
|
pathToCSV: `${csvPath}/member-csv-export.csv`,
|
|
|
|
headerMapping: defaultAllowedFields,
|
|
|
|
importLabel: {
|
|
|
|
name: 'Test Import'
|
|
|
|
},
|
|
|
|
user: {
|
|
|
|
email: 'test@example.com'
|
|
|
|
},
|
2022-10-19 13:33:47 +03:00
|
|
|
LabelModel: LabelModelStub,
|
|
|
|
forceInline: true
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
should.exist(result.meta);
|
|
|
|
should.exist(result.meta.stats);
|
|
|
|
should.exist(result.meta.stats.imported);
|
|
|
|
result.meta.stats.imported.should.equal(2);
|
|
|
|
|
|
|
|
should.exist(result.meta.stats.invalid);
|
|
|
|
should.deepEqual(result.meta.import_label, internalLabel);
|
|
|
|
|
|
|
|
should.exist(result.meta.originalImportSize);
|
|
|
|
result.meta.originalImportSize.should.equal(2);
|
|
|
|
|
|
|
|
fsWriteSpy.calledOnce.should.be.true();
|
|
|
|
|
|
|
|
// member records get inserted
|
|
|
|
membersApiStub.members.create.calledTwice.should.be.true();
|
|
|
|
|
|
|
|
should.equal(membersApiStub.members.create.args[0][1].context.import, true, 'inserts are done in the "import" context');
|
|
|
|
|
|
|
|
should.deepEqual(Object.keys(membersApiStub.members.create.args[0][0]), ['email', 'name', 'note', 'subscribed', 'created_at', 'labels']);
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].id, undefined, 'id field should not be taken from the user input');
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].email, 'member_complimentary_test@example.com');
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].name, 'bobby tables');
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].note, 'a note');
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].subscribed, true);
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].created_at, '2022-10-18T06:34:08.000Z');
|
|
|
|
should.equal(membersApiStub.members.create.args[0][0].deleted_at, undefined, 'deleted_at field should not be taken from the user input');
|
|
|
|
should.deepEqual(membersApiStub.members.create.args[0][0].labels, [{
|
|
|
|
name: 'user import label'
|
|
|
|
}]);
|
|
|
|
|
|
|
|
should.deepEqual(Object.keys(membersApiStub.members.create.args[1][0]), ['email', 'name', 'note', 'subscribed', 'created_at', 'labels']);
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].id, undefined, 'id field should not be taken from the user input');
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].email, 'member_stripe_test@example.com');
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].name, 'stirpey beaver');
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].note, 'testing notes');
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].subscribed, false);
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].created_at, '2022-10-18T07:31:57.000Z');
|
|
|
|
should.equal(membersApiStub.members.create.args[1][0].deleted_at, undefined, 'deleted_at field should not be taken from the user input');
|
|
|
|
should.deepEqual(membersApiStub.members.create.args[1][0].labels, [], 'no labels should be assigned');
|
|
|
|
|
|
|
|
// stripe customer import
|
|
|
|
membersApiStub.members.linkStripeCustomer.calledOnce.should.be.true();
|
|
|
|
should.equal(membersApiStub.members.linkStripeCustomer.args[0][0].customer_id, 'cus_MdR9tqW6bAreiq');
|
|
|
|
should.equal(membersApiStub.members.linkStripeCustomer.args[0][0].member_id, 'test_member_id');
|
|
|
|
|
2022-10-24 13:03:44 +03:00
|
|
|
// complimentary_plan import
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
membersApiStub.members.update.calledOnce.should.be.true();
|
|
|
|
should.deepEqual(membersApiStub.members.update.args[0][0].products, [{
|
|
|
|
id: 'default_product_id'
|
|
|
|
}]);
|
|
|
|
should.deepEqual(membersApiStub.members.update.args[0][1].id, 'test_member_id');
|
|
|
|
});
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
|
|
|
|
2022-08-23 22:19:30 +03:00
|
|
|
describe('sendErrorEmail', function () {
|
|
|
|
it('should send email with errors for invalid CSV file', async function () {
|
2022-10-13 09:21:08 +03:00
|
|
|
const importer = buildMockImporterInstance();
|
2022-08-23 22:19:30 +03:00
|
|
|
|
|
|
|
await importer.sendErrorEmail({
|
|
|
|
emailRecipient: 'test@example.com',
|
|
|
|
emailSubject: 'Your member import was unsuccessful',
|
|
|
|
emailContent: 'Import was unsuccessful',
|
|
|
|
errorCSV: 'id,email,invalid email',
|
|
|
|
importLabel: {name: 'Test import'}
|
|
|
|
});
|
|
|
|
|
|
|
|
sendEmailStub.calledWith({
|
|
|
|
to: 'test@example.com',
|
|
|
|
subject: 'Your member import was unsuccessful',
|
|
|
|
html: 'Import was unsuccessful',
|
|
|
|
forceTextContent: true,
|
|
|
|
attachments: [
|
|
|
|
{
|
|
|
|
filename: 'Test import - Errors.csv',
|
|
|
|
content: 'id,email,invalid email',
|
|
|
|
contentType: 'text/csv',
|
|
|
|
contentDisposition: 'attachment'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}).should.be.true();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-07-21 16:28:39 +03:00
|
|
|
describe('prepare', function () {
|
|
|
|
it('processes a basic valid import file for members', async function () {
|
2022-10-13 09:21:08 +03:00
|
|
|
const membersImporter = buildMockImporterInstance();
|
2021-07-21 16:28:39 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
const result = await membersImporter.prepare(`${csvPath}/single-column-with-header.csv`, defaultAllowedFields);
|
2021-07-21 16:28:39 +03:00
|
|
|
|
2022-10-13 10:04:22 +03:00
|
|
|
should.exist(result.filePath);
|
|
|
|
result.filePath.should.match(/\/members-importer\/test\/fixtures\/Members Import/);
|
2021-07-21 16:28:39 +03:00
|
|
|
|
|
|
|
result.batches.should.equal(2);
|
|
|
|
should.exist(result.metadata);
|
2021-07-21 18:25:41 +03:00
|
|
|
|
|
|
|
fsWriteSpy.calledOnce.should.be.true();
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
2021-11-04 20:48:39 +03:00
|
|
|
|
|
|
|
it('Does not include columns not in the original CSV or mapped', async function () {
|
2022-10-13 09:21:08 +03:00
|
|
|
const membersImporter = buildMockImporterInstance();
|
2021-11-04 20:48:39 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
await membersImporter.prepare(`${csvPath}/single-column-with-header.csv`, defaultAllowedFields);
|
2021-11-04 20:48:39 +03:00
|
|
|
|
|
|
|
const fileContents = fsWriteSpy.firstCall.args[1];
|
|
|
|
|
|
|
|
fileContents.should.match(/^email,labels\r\n/);
|
|
|
|
});
|
2022-10-13 11:16:37 +03:00
|
|
|
|
|
|
|
it('It supports "subscribed_to_emails" column header ouf of the box', async function (){
|
|
|
|
const membersImporter = buildMockImporterInstance();
|
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
await membersImporter.prepare(`${csvPath}/subscribed-to-emails-header.csv`, defaultAllowedFields);
|
2022-10-13 11:16:37 +03:00
|
|
|
|
|
|
|
const fileContents = fsWriteSpy.firstCall.args[1];
|
|
|
|
|
|
|
|
fileContents.should.match(/^email,subscribed_to_emails,labels\r\n/);
|
|
|
|
});
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
2022-10-13 10:16:09 +03:00
|
|
|
|
|
|
|
describe('perform', function () {
|
|
|
|
it('performs import on a single csv file', async function () {
|
|
|
|
const importer = buildMockImporterInstance();
|
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
const result = await importer.perform(`${csvPath}/single-column-with-header.csv`, defaultAllowedFields);
|
2022-10-13 10:16:09 +03:00
|
|
|
|
2022-10-13 11:16:37 +03:00
|
|
|
assert.equal(membersApiStub.members.create.args[0][0].email, 'jbloggs@example.com');
|
|
|
|
assert.deepEqual(membersApiStub.members.create.args[0][0].labels, []);
|
|
|
|
|
|
|
|
assert.equal(membersApiStub.members.create.args[1][0].email, 'test@example.com');
|
|
|
|
assert.deepEqual(membersApiStub.members.create.args[1][0].labels, []);
|
|
|
|
|
|
|
|
assert.equal(result.total, 2);
|
|
|
|
assert.equal(result.imported, 2);
|
|
|
|
assert.equal(result.errors.length, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('performs import on a csv file "subscribed_to_emails" column header', async function () {
|
|
|
|
const importer = buildMockImporterInstance();
|
|
|
|
|
|
|
|
const result = await importer.perform(`${csvPath}/subscribed-to-emails-header.csv`);
|
|
|
|
|
|
|
|
assert.equal(membersApiStub.members.create.args[0][0].email, 'jbloggs@example.com');
|
|
|
|
assert.equal(membersApiStub.members.create.args[0][0].subscribed, true);
|
|
|
|
assert.deepEqual(membersApiStub.members.create.args[0][0].labels, []);
|
|
|
|
|
|
|
|
assert.equal(membersApiStub.members.create.args[1][0].email, 'test@example.com');
|
|
|
|
assert.equal(membersApiStub.members.create.args[1][0].subscribed, false);
|
|
|
|
assert.deepEqual(membersApiStub.members.create.args[1][0].labels, []);
|
|
|
|
|
2022-10-13 10:16:09 +03:00
|
|
|
assert.equal(result.total, 2);
|
|
|
|
assert.equal(result.imported, 2);
|
|
|
|
assert.equal(result.errors.length, 0);
|
|
|
|
});
|
|
|
|
});
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|