// SPDX-License-Identifier: Apache-2.0
import { expect } from 'chai';
import sinon from 'sinon';
import { DefaultKindClient } from '../../../../../src/integration/kind/impl/default-kind-client.js';
import { KindExecutionBuilder } from '../../../../../src/integration/kind/execution/kind-execution-builder.js';
import { ClusterCreateResponse } from '../../../../../src/integration/kind/model/create-cluster/cluster-create-response.js';
import { KindExecution } from '../../../../../src/integration/kind/execution/kind-execution.js';
describe('DefaultKindClient - createCluster', () => {
    let client;
    let executionBuilderStub;
    let executionStub;
    beforeEach(() => {
        client = new DefaultKindClient('/usr/local/bin/kind');
        executionBuilderStub = sinon.createStubInstance(KindExecutionBuilder);
        executionStub = sinon.createStubInstance(KindExecution);
        // Set up the builder stub
        executionBuilderStub.build.returns(executionStub);
        sinon.stub(KindExecutionBuilder.prototype, 'build').returns(executionStub);
    });
    afterEach(() => {
        sinon.restore();
    });
    it('should create a cluster and parse the response correctly', async () => {
        // Use a different name pattern to test regex extraction
        const clusterName = 'dev-cluster';
        const contextName = 'kind-dev-cluster';
        // Create output that contains the necessary patterns but with different text
        executionStub.responseAs.callsFake((responseClass) => {
            const output = `Creating cluster "${clusterName}" ... ✓ Various steps completed ✓ Set kubectl context to "${contextName}"`;
            return Promise.resolve(new responseClass(output));
        });
        const result = await client.createCluster(clusterName);
        expect(result).to.be.instanceOf(ClusterCreateResponse);
        expect(result.name).to.equal(clusterName);
        expect(result.context).to.equal(contextName);
    });
    it('should throw if responseAs throws', async () => {
        executionStub.responseAs.rejects(new Error('fail'));
        try {
            await client.createCluster('test-cluster');
            expect.fail('Expected error');
        }
        catch (error) {
            expect(error.message).to.equal('fail');
        }
    });
    it('should extract cluster name with special characters', async () => {
        const clusterName = 'my.cluster-with_special-chars_123';
        const contextName = `kind-${clusterName}`;
        executionStub.responseAs.callsFake((responseClass) => {
            const output = `Creating cluster "${clusterName}" ... [some logs] Set kubectl context to "${contextName}"`;
            return Promise.resolve(new responseClass(output));
        });
        const result = await client.createCluster(clusterName);
        expect(result.name).to.equal(clusterName);
        expect(result.context).to.equal(contextName);
    });
    it('should handle missing context information gracefully', async () => {
        const clusterName = 'partial-output-cluster';
        executionStub.responseAs.callsFake((responseClass) => {
            // Output missing the context part
            const output = `Creating cluster "${clusterName}" ... ✓ Various steps completed`;
            return Promise.resolve(new responseClass(output));
        });
        const result = await client.createCluster(clusterName);
        expect(result.name).to.equal(clusterName);
        expect(result.context).to.be.undefined;
    });
    it('should pass cluster name and options to execution builder', async () => {
        const clusterName = 'options-test-cluster';
        const options = {
            config: './custom-config.yaml',
            image: 'custom/node:v1.27.0',
            name: clusterName,
            retain: true,
            wait: '120s',
        };
        // Create a spy to track subcommands and arguments
        const subcommandsSpy = sinon.spy(KindExecutionBuilder.prototype, 'subcommands');
        const argumentSpy = sinon.spy(KindExecutionBuilder.prototype, 'argument');
        const flagSpy = sinon.spy(KindExecutionBuilder.prototype, 'flag');
        await client.createCluster(clusterName, options);
        // Verify subcommands were called correctly
        expect(subcommandsSpy.calledWith('create', 'cluster')).to.be.true;
        // Verify arguments were set correctly
        expect(argumentSpy.calledWith('name', clusterName)).to.be.true;
        expect(argumentSpy.calledWith('image', options.image)).to.be.true;
        expect(argumentSpy.calledWith('config', options.config)).to.be.true;
        expect(argumentSpy.calledWith('wait', options.wait)).to.be.true;
        // Verify flags were set correctly
        expect(flagSpy.calledWith('retain')).to.be.true;
    });
    it('should handle boolean options correctly', async () => {
        const clusterName = 'boolean-options-cluster';
        // Test with boolean options turned on and off
        const options = {
            name: clusterName,
            retain: true,
        };
        // Create a spy to track flag calls
        const flagSpy = sinon.spy(KindExecutionBuilder.prototype, 'flag');
        const argumentSpy = sinon.spy(KindExecutionBuilder.prototype, 'argument');
        await client.createCluster(clusterName, options);
        // Should include options that are true
        expect(flagSpy.calledWith('retain')).to.be.true;
        // Should set name as argument
        expect(argumentSpy.calledWith('name', clusterName)).to.be.true;
    });
    it('should handle string options correctly', async () => {
        const clusterName = 'mixed-options-cluster';
        const options = {
            wait: '60s',
            image: 'kindest/node:v1.29.0',
            name: clusterName,
        };
        // Create a spy to track argument calls
        const argumentSpy = sinon.spy(KindExecutionBuilder.prototype, 'argument');
        await client.createCluster(clusterName, options);
        // Options should be passed as arguments
        expect(argumentSpy.calledWith('wait', '60s')).to.be.true;
        expect(argumentSpy.calledWith('image', 'kindest/node:v1.29.0')).to.be.true;
    });
    it('should handle no options provided', async () => {
        const clusterName = 'default-options-cluster';
        const contextName = 'kind-default-options-cluster';
        executionStub.responseAs.callsFake((responseClass) => {
            const output = `Creating cluster "${clusterName}" ... completed ... Set kubectl context to "${contextName}"`;
            return Promise.resolve(new responseClass(output));
        });
        // Create a spy to track argument calls
        const argumentSpy = sinon.spy(KindExecutionBuilder.prototype, 'argument');
        // Call without options object
        const result = await client.createCluster(clusterName);
        // Verify only name parameter was set
        expect(argumentSpy.calledWith('name', clusterName)).to.be.true;
        // Check number of calls to argument to verify no other arguments were set
        // Adding 1 for the name argument
        expect(argumentSpy.callCount).to.equal(1);
        // Response should be correct
        expect(result.name).to.equal(clusterName);
        expect(result.context).to.equal(contextName);
    });
});
//# sourceMappingURL=create-cluster.test.js.map