diff --git a/packages/graph/src/-private/-diff.ts b/packages/graph/src/-private/-diff.ts index 7c40423f7fa..15e45e66a41 100644 --- a/packages/graph/src/-private/-diff.ts +++ b/packages/graph/src/-private/-diff.ts @@ -398,7 +398,7 @@ export function rollbackRelationship( op: 'replaceRelatedRecords', record: identifier, field, - value: relationship.remoteState, + value: relationship.remoteState.slice(), }, false ); diff --git a/tests/main/tests/integration/relationships/rollback-test.ts b/tests/main/tests/integration/relationships/rollback-test.ts index 56789262f25..e078d83af18 100644 --- a/tests/main/tests/integration/relationships/rollback-test.ts +++ b/tests/main/tests/integration/relationships/rollback-test.ts @@ -4,6 +4,7 @@ import { setupTest } from 'ember-qunit'; import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; import type Store from '@ember-data/store'; +import { recordIdentifierFor } from '@ember-data/store'; import type { StableRecordIdentifier } from '@warp-drive/core-types'; class App extends Model { @@ -398,6 +399,58 @@ module('Integration | Relationships | Rollback', function (hooks) { assert.arrayStrictEquals(changed, [], 'belongsTo has rolled back'); assert.strictEqual(config.app, store.peekRecord('app', '1') as App, 'belongsTo has rolled back'); }); + + test('relationship rollback can be repeated', function (assert) { + class Message extends Model { + @attr declare msg: string; + } + class Job extends Model { + @attr declare name: string; + @hasMany('message', { async: false, inverse: null }) declare messages: Message[]; + } + + this.owner.register('model:job', Job); + this.owner.register('model:message', Message); + const store = this.owner.lookup('service:store') as Store; + + const job = store.push({ + data: { + id: '1', + type: 'job', + attributes: { + name: 'First Job', + }, + }, + }) as Job; + + const msg1 = store.push({ + data: { + id: '1', + type: 'message', + attributes: { + msg: 'First Message', + }, + }, + }) as Message; + assert.strictEqual(job.messages.length, 0, 'job has 0 messages'); + const jobIdentifier = recordIdentifierFor(job); + + // add message, assert state, rollback, assert state is clean + job.messages.push(msg1); + assert.strictEqual(job.messages.length, 1, 'job has 1 message'); + + const rollbackResult = store.cache.rollbackRelationships(jobIdentifier); + assert.strictEqual(rollbackResult.length, 1, '1 rollbackRelations'); + assert.strictEqual(job.messages.length, 0, 'job has no message'); + + // repeat the scenario to add a message and rollback + job.messages.push(msg1); + assert.strictEqual(job.messages.length, 1, 'job has 1 message'); + + const rollbackResult2 = store.cache.rollbackRelationships(jobIdentifier); + assert.strictEqual(rollbackResult2.length, 1, '1 rollbackRelations'); + assert.strictEqual(job.messages.length, 0, 'job has no message'); + }); }); module('.changedRelationships', function () {