| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- import { mergeConfig } from '@vendure/core';
- import { createTestEnvironment } from '@vendure/testing';
- import { fail } from 'assert';
- import gql from 'graphql-tag';
- import path from 'path';
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
- import { initialData } from '../../../e2e-common/e2e-initial-data';
- import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
- import {
- TransactionTestPlugin,
- TRIGGER_ATTEMPTED_READ_EMAIL,
- TRIGGER_ATTEMPTED_UPDATE_EMAIL,
- TRIGGER_NO_OPERATION,
- } from './fixtures/test-plugins/transaction-test-plugin';
- type DBType = 'mysql' | 'postgres' | 'sqlite' | 'sqljs';
- const itIfDb = (dbs: DBType[]) => {
- return dbs.includes((process.env.DB as DBType) || 'sqljs') ? it : it.skip;
- };
- describe('Transaction infrastructure', () => {
- const { server, adminClient } = createTestEnvironment(
- mergeConfig(testConfig(), {
- plugins: [TransactionTestPlugin],
- }),
- );
- beforeAll(async () => {
- await server.init({
- initialData,
- productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
- customerCount: 0,
- });
- await adminClient.asSuperAdmin();
- }, TEST_SETUP_TIMEOUT_MS);
- afterAll(async () => {
- await server.destroy();
- });
- it('non-failing mutation', async () => {
- const { createTestAdministrator } = await adminClient.query(CREATE_ADMIN, {
- emailAddress: 'test1',
- fail: false,
- });
- expect(createTestAdministrator.emailAddress).toBe('test1');
- expect(createTestAdministrator.user.identifier).toBe('test1');
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(2);
- expect(!!verify.admins.find((a: any) => a.emailAddress === 'test1')).toBe(true);
- expect(!!verify.users.find((u: any) => u.identifier === 'test1')).toBe(true);
- });
- it('failing mutation', async () => {
- try {
- await adminClient.query(CREATE_ADMIN, {
- emailAddress: 'test2',
- fail: true,
- });
- fail('Should have thrown');
- } catch (e: any) {
- expect(e.message).toContain('Failed!');
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(2);
- expect(!!verify.admins.find((a: any) => a.emailAddress === 'test2')).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier === 'test2')).toBe(false);
- });
- it('failing mutation with promise concurrent execution', async () => {
- try {
- await adminClient.query(CREATE_N_ADMINS, {
- emailAddress: 'testN-',
- failFactor: 0.4,
- n: 10,
- });
- fail('Should have thrown');
- } catch (e) {
- expect(e.message).toContain('Failed!');
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(2);
- expect(!!verify.admins.find((a: any) => a.emailAddress.includes('testN'))).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier.includes('testN'))).toBe(false);
- });
- it('failing manual mutation', async () => {
- try {
- await adminClient.query(CREATE_ADMIN2, {
- emailAddress: 'test3',
- fail: true,
- });
- fail('Should have thrown');
- } catch (e: any) {
- expect(e.message).toContain('Failed!');
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(2);
- expect(!!verify.admins.find((a: any) => a.emailAddress === 'test3')).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier === 'test3')).toBe(false);
- });
- it('failing manual mutation without transaction', async () => {
- try {
- await adminClient.query(CREATE_ADMIN3, {
- emailAddress: 'test4',
- fail: true,
- });
- fail('Should have thrown');
- } catch (e: any) {
- expect(e.message).toContain('Failed!');
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(3);
- expect(!!verify.admins.find((a: any) => a.emailAddress === 'test4')).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier === 'test4')).toBe(true);
- });
- it('failing mutation inside connection.withTransaction() wrapper with request context', async () => {
- try {
- await adminClient.query(CREATE_ADMIN5, {
- emailAddress: 'test5',
- fail: true,
- noContext: false,
- });
- fail('Should have thrown');
- } catch (e: any) {
- expect(e.message).toContain('Failed!');
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(3);
- expect(!!verify.admins.find((a: any) => a.emailAddress === 'test5')).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier === 'test5')).toBe(false);
- });
- itIfDb(['postgres', 'mysql'])(
- 'failing mutation inside connection.withTransaction() wrapper with context and promise concurrent execution',
- async () => {
- try {
- await adminClient.query(CREATE_N_ADMINS2, {
- emailAddress: 'testN-',
- failFactor: 0.4,
- n: 10,
- });
- fail('Should have thrown');
- } catch (e) {
- expect(e.message).toMatch(
- /^Failed!|Query runner already released. Cannot run queries anymore.$/,
- );
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(3);
- expect(!!verify.admins.find((a: any) => a.emailAddress.includes('testN'))).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier.includes('testN'))).toBe(false);
- },
- );
- it('failing mutation inside connection.withTransaction() wrapper without request context', async () => {
- try {
- await adminClient.query(CREATE_ADMIN5, {
- emailAddress: 'test5',
- fail: true,
- noContext: true,
- });
- fail('Should have thrown');
- } catch (e: any) {
- expect(e.message).toContain('Failed!');
- }
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(2);
- expect(verify.users.length).toBe(3);
- expect(!!verify.admins.find((a: any) => a.emailAddress === 'test5')).toBe(false);
- expect(!!verify.users.find((u: any) => u.identifier === 'test5')).toBe(false);
- });
- it('non-failing mutation inside connection.withTransaction() wrapper with failing nested transactions and request context', async () => {
- await adminClient.query(CREATE_N_ADMINS3, {
- emailAddress: 'testNestedTransactionsN-',
- failFactor: 0.5,
- n: 2,
- });
- const { verify } = await adminClient.query(VERIFY_TEST);
- expect(verify.admins.length).toBe(3);
- expect(verify.users.length).toBe(4);
- expect(
- verify.admins.filter((a: any) => a.emailAddress.includes('testNestedTransactionsN')),
- ).toHaveLength(1);
- expect(
- verify.users.filter((u: any) => u.identifier.includes('testNestedTransactionsN')),
- ).toHaveLength(1);
- });
- it('event do not publish after transaction rollback', async () => {
- TransactionTestPlugin.reset();
- try {
- await adminClient.query(CREATE_N_ADMINS, {
- emailAddress: TRIGGER_NO_OPERATION,
- failFactor: 0.5,
- n: 2,
- });
- fail('Should have thrown');
- } catch (e) {
- expect(e.message).toContain('Failed!');
- }
- // Wait a bit to see an events in handler
- await new Promise(resolve => setTimeout(resolve, 100));
- expect(TransactionTestPlugin.callHandler).not.toHaveBeenCalled();
- expect(TransactionTestPlugin.errorHandler).not.toHaveBeenCalled();
- });
- // Testing https://github.com/vendurehq/vendure/issues/520
- it('passing transaction via EventBus', async () => {
- TransactionTestPlugin.reset();
- const { createTestAdministrator } = await adminClient.query(CREATE_ADMIN, {
- emailAddress: TRIGGER_ATTEMPTED_UPDATE_EMAIL,
- fail: false,
- });
- await TransactionTestPlugin.eventHandlerComplete$.toPromise();
- expect(createTestAdministrator.emailAddress).toBe(TRIGGER_ATTEMPTED_UPDATE_EMAIL);
- expect(TransactionTestPlugin.errorHandler).not.toHaveBeenCalled();
- });
- // Testing https://github.com/vendurehq/vendure/issues/1107
- it('passing transaction via EventBus with delay in committing transaction', async () => {
- TransactionTestPlugin.reset();
- const { createTestAdministrator4 } = await adminClient.query(CREATE_ADMIN4, {
- emailAddress: TRIGGER_ATTEMPTED_READ_EMAIL,
- fail: false,
- });
- await TransactionTestPlugin.eventHandlerComplete$.toPromise();
- expect(createTestAdministrator4.emailAddress).toBe(TRIGGER_ATTEMPTED_READ_EMAIL);
- expect(TransactionTestPlugin.errorHandler).not.toHaveBeenCalled();
- });
- });
- const ADMIN_FRAGMENT = gql`
- fragment CreatedAdmin on Administrator {
- id
- emailAddress
- user {
- id
- identifier
- }
- }
- `;
- const CREATE_ADMIN = gql`
- mutation CreateTestAdmin($emailAddress: String!, $fail: Boolean!) {
- createTestAdministrator(emailAddress: $emailAddress, fail: $fail) {
- ...CreatedAdmin
- }
- }
- ${ADMIN_FRAGMENT}
- `;
- const CREATE_ADMIN2 = gql`
- mutation CreateTestAdmin2($emailAddress: String!, $fail: Boolean!) {
- createTestAdministrator2(emailAddress: $emailAddress, fail: $fail) {
- ...CreatedAdmin
- }
- }
- ${ADMIN_FRAGMENT}
- `;
- const CREATE_ADMIN3 = gql`
- mutation CreateTestAdmin3($emailAddress: String!, $fail: Boolean!) {
- createTestAdministrator3(emailAddress: $emailAddress, fail: $fail) {
- ...CreatedAdmin
- }
- }
- ${ADMIN_FRAGMENT}
- `;
- const CREATE_ADMIN4 = gql`
- mutation CreateTestAdmin4($emailAddress: String!, $fail: Boolean!) {
- createTestAdministrator4(emailAddress: $emailAddress, fail: $fail) {
- ...CreatedAdmin
- }
- }
- ${ADMIN_FRAGMENT}
- `;
- const CREATE_ADMIN5 = gql`
- mutation CreateTestAdmin5($emailAddress: String!, $fail: Boolean!, $noContext: Boolean!) {
- createTestAdministrator5(emailAddress: $emailAddress, fail: $fail, noContext: $noContext) {
- ...CreatedAdmin
- }
- }
- ${ADMIN_FRAGMENT}
- `;
- const CREATE_N_ADMINS = gql`
- mutation CreateNTestAdmins($emailAddress: String!, $failFactor: Float!, $n: Int!) {
- createNTestAdministrators(emailAddress: $emailAddress, failFactor: $failFactor, n: $n)
- }
- `;
- const CREATE_N_ADMINS2 = gql`
- mutation CreateNTestAdmins2($emailAddress: String!, $failFactor: Float!, $n: Int!) {
- createNTestAdministrators2(emailAddress: $emailAddress, failFactor: $failFactor, n: $n)
- }
- `;
- const CREATE_N_ADMINS3 = gql`
- mutation CreateNTestAdmins3($emailAddress: String!, $failFactor: Float!, $n: Int!) {
- createNTestAdministrators3(emailAddress: $emailAddress, failFactor: $failFactor, n: $n)
- }
- `;
- const VERIFY_TEST = gql`
- query VerifyTest {
- verify {
- admins {
- id
- emailAddress
- }
- users {
- id
- identifier
- }
- }
- }
- `;
|