Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion packages/core/e2e/import.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */

import { omit } from '@vendure/common/lib/omit';
import { CurrencyCode, LanguageCode } from '@vendure/common/lib/generated-types';
import { User } from '@vendure/core';
import { createTestEnvironment } from '@vendure/testing';
import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
import * as fs from 'node:fs';
import http from 'node:http';
import path from 'node:path';
Expand All @@ -12,6 +13,7 @@ import { initialData } from '../../../e2e-common/e2e-initial-data';
import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';

import { graphql } from './graphql/graphql-admin';
import { createChannelDocument } from './graphql/shared-definitions';

describe('Import resolver', () => {
const { server, adminClient } = createTestEnvironment({
Expand Down Expand Up @@ -297,6 +299,67 @@ describe('Import resolver', () => {
expect(tShirt.variants[0].options.length).toBe(2);
}, 30000);

// https://github.com/vendure-ecommerce/vendure/issues/4673
it('imports facets and variantFacets when re-importing into a new channel', async () => {
const SECOND_CHANNEL_TOKEN = 'second_channel_token';

// Create a new channel
await adminClient.query(createChannelDocument, {
input: {
code: 'second-channel',
token: SECOND_CHANNEL_TOKEN,
defaultLanguageCode: LanguageCode.en,
currencyCode: CurrencyCode.USD,
pricesIncludeTax: false,
defaultShippingZoneId: 'T_1',
defaultTaxZoneId: 'T_1',
},
});

// Switch to the new channel
adminClient.setChannelToken(SECOND_CHANNEL_TOKEN);

// Import the same CSV into the new channel
const csvFile = path.join(__dirname, 'fixtures', 'product-import.csv');
const result = await adminClient.fileUploadMutation({
mutation: importProductsDocument1,
filePaths: [csvFile],
mapVariables: () => ({ csvFile: null }),
});

expect(result.importProducts.errors).toEqual([
'Invalid Record Length: header length is 20, got 1 on line 8',
]);
expect(result.importProducts.imported).toBe(4);

// Query products in the new channel
const productResult = await adminClient.query(getProductsDocument1, {
options: {},
});

expect(productResult.products.totalItems).toBe(4);

const paperStretcher = productResult.products.items.find(
(p: any) => p.name === 'Perfect Paper Stretcher',
);
const smock = productResult.products.items.find((p: any) => p.name === 'Artists Smock');

if (!paperStretcher || !smock) {
throw new Error('Expected products to be found in second channel');
}

const byName = (e: { name: string }) => e.name;

// Verify product-level facets are present in the new channel
expect(smock.facetValues.map(byName).sort()).toEqual(['Denim', 'clothes']);

// Verify variant-level facets are present in the new channel
expect(paperStretcher.variants[0].facetValues.map(byName).sort()).toEqual(['Accessory', 'KB']);

// Switch back to default channel
adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
}, 30000);

describe('asset urls', () => {
let staticServer: http.Server;

Expand Down
17 changes: 17 additions & 0 deletions packages/core/src/data-import/providers/importer/importer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ export class Importer {
rows: ParsedProductWithVariants[],
onProgress: OnProgressFn,
): Promise<string[]> {
// Clear caches to avoid stale references from previous imports
// (e.g. when importing into a different channel)
this.facetMap.clear();
this.facetValueMap.clear();
this.taxCategoryMatches = {};
let errors: string[] = [];
let imported = 0;
const languageCode = ctx.languageCode;
Expand Down Expand Up @@ -357,6 +362,12 @@ export class Importer {
);
if (existing) {
facetEntity = existing;
await this.channelService.assignToChannels(
ctx,
Facet,
facetEntity.id,
[ctx.channelId],
);
} else {
facetEntity = await this.facetService.create(ctx, {
isPrivate: false,
Expand All @@ -381,6 +392,12 @@ export class Importer {
const existing = facetEntity.values.find(v => v.name === valueName);
if (existing) {
facetValueEntity = existing;
await this.channelService.assignToChannels(
ctx,
FacetValue,
facetValueEntity.id,
[ctx.channelId],
);
} else {
facetValueEntity = await this.facetValueService.create(ctx, facetEntity, {
code: normalizeString(valueName, '-'),
Expand Down
Loading